R的plot_ly动画在有两个轨迹的情况下,动画滑块存在问题。

huangapple go评论65阅读模式
英文:

R plot_ly animation with 2 traces has issue with animation slider

问题

我正在处理一个动画,其中x轴上有一个因子水平,而动画中的frame也是相同的因子水平。我想要显示完整的数据集作为静止的,并且有一个单独的轨迹随着时间在动画中的时间序列上移动。下面是一个示例,展示了我遇到的问题。任何帮助将不胜感激!

library(dplyr)
library(plotly)

#### create data
dat <- expand.grid(x = 1:5, f = 1:5)
dat <- dat %>% mutate(y = x^f/10) %>%
  arrange(desc(f)) %>%
  mutate(fr = letters[f], 
         fr = factor(fr, levels = unique(fr))) %>%
  data.frame()

Three plots - two of them show each of the 2 traces separately (plotting correctly), and the third show the traces combined, with the animation slider reversing order erroneously.

### stationary plot of all data - showing correct ordering of x-axis values
plot_ly(dat) %>%
  add_trace(x = ~fr,
            y = ~y,
            type = "scatter",
            mode = "markers") 

#### animated trace, showing correct ordering of the animation slider(from e to a)
plot_ly(dat) %>%
  add_trace(x = ~fr,
            y = ~y,
            frame = ~fr,
            type = "scatter",
            mode = "markers") %>%
  animation_opts(frame = 500) 

#### both traces combined, showing the problem - the x-axis is ordered correctly, 
#### but the animation slider reversed order, now playing from a to e. e to a)
plot_ly(dat) %>%
     add_trace(x = ~fr,
               y = ~y,
               type = "scatter",
               mode = "markers") %>%
     add_trace(x = ~fr,
               y = ~y,
               frame = ~fr,
               type = "scatter",
               mode = "markers") %>%
     animation_opts(frame = 500) %>%
     animation_slider()

编辑

我创建了一个更接近实际数据的数据集。使用答案中提供的fixer()函数运行时仍然会出现动画条的问题,我无法弄清楚为什么,考虑到它在原始的玩具数据集中完美运行...

dat <- data.frame(Date = seq(as.Date("2000-01-01"), as.Date("2000-04-01"), by = "1 day"),
                  N = rnorm(92, 0, 1)) %>%
            mutate(fr = format(Date, "%d-%b"),
                   fr = factor(fr, levels = unique(fr)))

plot_ly(dat) %>%
    add_trace(x = ~fr,
              y = ~N,
              type = "scatter",
              mode = "markers") %>%
   add_trace(x = ~fr,
             y = ~N,
             frame = ~fr,
             type = "scatter",
             mode = "markers") %>%
  animation_opts(frame = 500) %>%
  animation_slider() %>% fixer()  
英文:

I'm working on an animation with a factor level on the x-axis and the same factor level as the frame in the animation. I would like to show the full dataset as stationary, and have a single trace follow the time series over time in an animation. Below is a toy example showing the issue I'm seeing. Any help would be appreciated!

library(dplyr)
library(plotly)

#### create data
dat &lt;- expand.grid(x = 1:5, f = 1:5)
dat &lt;- dat %&gt;% mutate(y = x^f/10) %&gt;%
  arrange(desc(f)) %&gt;%
  mutate(fr = letters[f], 
      fr = factor(fr, levels = unique(fr))) %&gt;%
  data.frame()

Three plots - two of them show each of the 2 traces separately (plotting correctly), and the third show the traces combined, with the animation slider reversing order erroneously.

### stationary plot of all data - showing correct ordering of x-axis values
plot_ly(dat) %&gt;%
  add_trace(x = ~fr,
            y = ~y,
            type = &quot;scatter&quot;,
            mode = &quot;markers&quot;) 

#### animated trace, showing correct ordering of the animation slider(from e to a)
plot_ly(dat) %&gt;%
  add_trace(x = ~fr,
            y = ~y,
            frame = ~fr,
            type = &quot;scatter&quot;,
            mode = &quot;markers&quot;) %&gt;%
  animation_opts(frame = 500) 

#### both traces combined, showing the problem - the x-axis is ordered correctly, 
#### but the animation slider reversed order, now playing from a to e. e to a)
plot_ly(dat) %&gt;%
     add_trace(x = ~fr,
               y = ~y,
               type = &quot;scatter&quot;,
               mode = &quot;markers&quot;) %&gt;%
     add_trace(x = ~fr,
               y = ~y,
               frame = ~fr,
               type = &quot;scatter&quot;,
               mode = &quot;markers&quot;) %&gt;%
     animation_opts(frame = 500) %&gt;%
     animation_slider()

EDIT

I created a dataset that is closer to my actual data. Running it with the fixer() function provided in the answer is still messing up the animation bar, and I can't figure out why, considering that it works perfectly with the original toy dataset...

dat &lt;- data.frame(Date = seq(as.Date(&quot;2000-01-01&quot;), as.Date(&quot;2000-04-01&quot;), by = &quot;1 day&quot;),
                  N = rnorm(92, 0, 1)) %&gt;%
            mutate(fr = format(Date, &quot;%d-%b&quot;),
                fr = factor(fr, levels = unique(fr)))

plot_ly(dat) %&gt;%
    add_trace(x = ~fr,
            y = ~N,
            type = &quot;scatter&quot;,
            mode = &quot;markers&quot;) %&gt;%
   add_trace(x = ~fr,
            y = ~N,
            frame = ~fr,
            type = &quot;scatter&quot;,
            mode = &quot;markers&quot;) %&gt;%
  animation_opts(frame = 500) %&gt;%
  animation_slider() %&gt;% fixer()  

答案1

得分: 1

我无法找到一个可以解决这个问题的参数,也无法通过重新排列调用的函数来解决。这真的很烦人,是吗?

这里有一个解决方法,虽然它能够解决问题,但并不适用于一般的使用。

我提供了一个名为fixer()的函数。在这个函数中,有一行代码以plt$x$data[[2]]开头。2是根据你调用轨迹的顺序确定的。由于frames轨迹是第二个调用的,所以这里是2。

除此之外,代码中的注释是为了解释如何以及为什么这样做。如果有任何不清楚或不符合你的预期,请告诉我。

fixer <- function(plt) {
  plt <- plotly_build(plt)                   # 构建以获取数据
                                             # 捕获绘图中当前动画的顺序
  curOrd <- invisible(lapply(1:length(plt$x$frames), function(j) {
    plt$x$frames[[j]]$name
  })) %>% unlist()
  
  fixOrd <- match(curOrd, levels(dat$fr))    # 比较当前顺序;获取索引以进行修复
  plt$x$frames <- plt$x$frames[fixOrd]       # 重新排列帧和滑块(步骤)
  plt$x$layout$sliders[[1]]$steps <- plt$x$layout$sliders[[1]]$steps[fixOrd]

                                       # 更改基本动画帧(当不进行动画时)
  plt$x$data[[2]] <- plt$x$frames[[1]]$data[[1]]
  plt # 返回绘图
}

plot_ly(dat) %>%
  add_trace(x = ~fr,
            y = ~y,
            type = "scatter",
            mode = "markers") %>%
  add_trace(x = ~fr,
            y = ~y,
            frame = ~fr,
            type = "scatter",
            mode = "markers") %>%
  animation_opts(frame = 500) %>%
  animation_slider() %>% fixer()      ## <<-- 这是新加的!

R的plot_ly动画在有两个轨迹的情况下,动画滑块存在问题。

英文:

I wasn't able to find a parameter that would address this issue, nor some rearrangement of the functions called. It's pretty annoying, ya?

Here's a workaround—that while it works, isn't great for in general use.

I've provided the function fixer(). In that function, there's a line of code that starts with plt$x$data[[2]]. The 2 was determined by the order in which you called your traces. Since the frames trace was called second, this is a two.

Other than that, the comments in the code are there to explain the how and why. If anything's unclear or doesn't work as you expected, please let me know.

fixer &lt;- function(plt) {
  plt &lt;- plotly_build(plt)                   # build to get data
                                             # capture current animation order in plot
  curOrd &lt;- invisible(lapply(1:length(plt$x$frames), function(j) {
    plt$x$frames[[j]]$name
  })) %&gt;% unlist()
  
  fixOrd &lt;- match(curOrd, levels(dat$fr))    # compare current order; get index to fix
  plt$x$frames &lt;- plt$x$frames[fixOrd]       # rearrange frames &amp; slider (steps)
  plt$x$layout$sliders[[1]]$steps &lt;- plt$x$layout$sliders[[1]]$steps[fixOrd]

                                       # change the base anim frame (when not animating)
  plt$x$data[[2]] &lt;- plt$x$frames[[1]]$data[[1]]
  plt # return plot
}

plot_ly(dat) %&gt;%
  add_trace(x = ~fr,
            y = ~y,
            type = &quot;scatter&quot;,
            mode = &quot;markers&quot;) %&gt;%
  add_trace(x = ~fr,
            y = ~y,
            frame = ~fr,
            type = &quot;scatter&quot;,
            mode = &quot;markers&quot;) %&gt;%
  animation_opts(frame = 500) %&gt;%
  animation_slider() %&gt;% fixer()      ## &lt;&lt;-- I&#39;m new!

R的plot_ly动画在有两个轨迹的情况下,动画滑块存在问题。

huangapple
  • 本文由 发表于 2023年8月9日 02:26:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76862268.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定