accumulate_by <- function(dat, var) {
var <- lazyeval::f_eval(var, dat)
lvls <- plotly:::getLevels(var)
dats <- lapply(seq_along(lvls), function(x) {
cbind(dat[var %in% lvls[seq(1, x)], ], frame = lvls[[x]])
})
dplyr::bind_rows(dats)
}
d <- txhousing %>%
filter(year > 2005, city %in% c("Abilene", "Bay Area")) %>%
accumulate_by(~date)
If you implement a cumulative animation in the manner of the function above, the number of rows will increase too much.
I use a thousand frames and a row of ten thousand. Because of the large number of data, the work in progress has been disturbed.
https://plot.ly/r/cumulative-animations/
Is there any way to create a cumulative animation other than the example? Help me!
I'm currently facing the same issue. The approach described here is not applicable for a few thousand rows of data.
I don't have a fully working solution, but my idea was to adapt the x-axis range based on the slider value instead of re-using the data for each frame (see example plot p_range_slider
). This unfortunately doesn't provide us with the "Play"-button.
I thought it might be possible to use animation_slider()
in a similar way but the steps
argument passed to animation_slider()
is not evaluated (see example plot p_animation_slider
). The steps remain tied to the animation frames (as stated in ?animation_slider
).
Update: this behaviour is intended by design see the sources:
# don't let the user override steps
slider$steps <- steps
Also building a subplot
of both sharing the x-axis wasn't successful.
library(plotly)
DF <- data.frame(
n = 1:50,
x = seq(0, 12, length = 50),
y = runif(n = 50, min = 0, max = 10)
)
steps <- list()
for (i in seq_len(nrow(DF))) {
steps[[i]] <- list(
args = list("xaxis", list(range = c(0, i))),
label = i,
method = "relayout",
value = i
)
}
# Custom range slider -----------------------------------------------------
p_range_slider <- plot_ly(
DF,
x = ~ x,
y = ~ y,
type = "scatter",
mode = "markers"
) %>% layout(title = "Custom range slider",
xaxis = list(range = steps[[1]]$args[[2]]$range),
sliders = list(
list(
active = 0,
currentvalue = list(prefix = "X-max: "),
pad = list(t = 20),
steps = steps)))
p_range_slider
# Animation slider --------------------------------------------------------
p_animation_slider <- plot_ly(
DF,
x = ~ x,
y = ~ y,
type = "scatter",
mode = "markers",
frame = ~ n
) %>% layout(title = "Animation slider") %>% animation_slider(
active = 6,
currentvalue = list(prefix = "X-max: "),
pad = list(t = 20),
steps = steps # custom steps are ignored
)
p_animation_slider
# subplot(p_range_slider, p_animation_slider, nrows = 2, margin = 0.05, shareX = TRUE)
It seems for this approach to work animation_slider()
would need to allow it's steps
argument to perform custom actions (untied from the defined frames). Any other Ideas to approach this are highly appreciated.
Maybe it is possible to reproduce this approach for the python api using a filter (avoids axis-rescaling) in R? - Filter in R
Here is an example on how to use filter transform and a custom range slider in R, however, still no animation (without precomputing each frame):
DF <- data.frame(x = rep(1:10, 2), y = runif(20), group = rep(LETTERS[1:2], each = 10))
steps <- list()
for (i in seq_along(unique(DF$x))) {
steps[[i]] <- list(
args = list('transforms[0].value', i),
label = i,
method = "restyle",
value = i
)
}
p_filter_slider <- plot_ly(
DF,
x = ~ x,
y = ~ y,
color = ~ group,
type = "scatter",
mode = "lines+markers",
transforms = list(
list(
type = 'filter',
target = 'x',
operation = '<=',
value = ~ x
)
)
) %>% layout(title = "Custom filter slider",
xaxis = list(range = c(0.5, length(unique(DF$x))+0.5)),
sliders = list(
list(
active = 0,
currentvalue = list(prefix = "X-max: "),
pad = list(t = 20),
steps = steps))
)
p_filter_slider
Additional Infos:
animation_slider documentation
JS slider attributes
Related GitHub issue
RStudio Community question
Here is the same question on the plotly forum.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With