英文:
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 <- 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()
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 <- 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()
答案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() ## <<-- 这是新加的!
英文:
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 <- function(plt) {
plt <- plotly_build(plt) # build to get data
# capture current animation order in plot
curOrd <- invisible(lapply(1:length(plt$x$frames), function(j) {
plt$x$frames[[j]]$name
})) %>% unlist()
fixOrd <- match(curOrd, levels(dat$fr)) # compare current order; get index to fix
plt$x$frames <- plt$x$frames[fixOrd] # rearrange frames & slider (steps)
plt$x$layout$sliders[[1]]$steps <- plt$x$layout$sliders[[1]]$steps[fixOrd]
# change the base anim frame (when not animating)
plt$x$data[[2]] <- plt$x$frames[[1]]$data[[1]]
plt # return plot
}
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() ## <<-- I'm new!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论