How to use multiple cores to make gganimate faster
This is a pull request, meaning that the code is available on GitHub as a branch, but hasn't yet been merged in gganimate
master.
You could clone it or copy the modified package directory on your system.
Then :
- make sure that
devtools
package is installed - open
gganimate.Rproj
- run
devtools::load_all(".")
The parallel version is ready to run :
anim <- ggplot(mtcars, aes(mpg, disp)) +
transition_states(gear, transition_length = 2, state_length = 1) +
enter_fade() +
exit_fade()
future::plan("sequential") ## default
t0 <- system.time(animate(anim))
print(t0)
# user system total
# 4.384615 1.360656 1.893855
future::plan("multiprocess", workers = 4L)
t1 <- system.time(animate(anim))
# user system total
# 1.30 0.61 3.58
print(t0 / t1)
# user system total
# 4.384615 1.360656 1.893855
To avoid load_all
you could open the DESCRIPTION
file and rename the package :
Package: gganimateparallel
Type: Package
Title: A Grammar of Animated Graphics
...
As vignettes seem to have difficulties to build, you can just remove the vignettes
directory.
Then RStudio / Build / Install and restart
or from the package's directory
Rcmd.exe INSTALL --no-multiarch --with-keep.source .
gganimateparallel
is now available on your system as a library.
Credits @HenrikBengtsson for the incredible job done on future
!
gganimate parallel - Provided file does not exist error
From trial and error, the following seems to be the problem: the package needs to be build from the GitHub pull request (a) (as described here) and needs to be named gganimate
to satisfy internal dependencies.
After setting up the environment correctly, parallel processing seems to work without using the plan(multisession, workers=7)
command, but using it appears to throw an error.
(see the discussion under the question for more details)
How to manage parallel processing with animated ggplot2-plot?
So, my solution:
split dates in
ncores
periodsget the plot for each period and save it as a GIF
read back all GIF and combine them
########################################################################
# setup
########################################################################
# creating some sample data for one year
# 4 categories; each category has a specific value per day
set.seed(1)
x <- data.frame(
rep(as.Date((Sys.Date()-364):Sys.Date(), origin="1970-01-01"),4),
c(rep("cat01",length.out=365),
rep("cat02",length.out=365),
rep("cat03",length.out=365),
rep("cat04",length.out=365)),
sample(0:50,365*4, replace=TRUE)
)
colnames(x) <- c("date", "category", "value")
# creating a cumulative measure making the graphs appear "growing"
library(dplyr)
x <- x %>%
as_tibble() %>%
arrange(date) %>%
mutate(date = as.character(date)) %>%
group_by(category) %>%
mutate(cumsum = cumsum(value))
y_max <- max(x$cumsum) + 500
library(doParallel)
all_dates <- unique(x$date)
ncores <- detectCores() - 1
ind_cluster <- sort(rep_len(1:ncores, length(all_dates)))
date_cluster <- split(all_dates, ind_cluster)
registerDoParallel(cl <- makeCluster(ncores))
tmp <- tempfile()
files <- foreach(ic = 1:ncores, .packages = c("tidyverse", "magick")) %dopar% {
img <- image_graph(1000, 700, res = 96)
x %>%
filter(date %in% date_cluster[[ic]]) %>%
group_by(date) %>%
do(
plot = ggplot(.) +
geom_col(aes(category, cumsum)) +
scale_y_continuous(expand = c(0, 0),
breaks = seq(0, y_max, 500),
limits = c(0, y_max))
) %>%
pmap(function(date, plot) {
print(plot + ggtitle(date))
NULL
})
dev.off()
image_write(image_animate(img, fps = 5), paste0(tmp, ic, ".gif"))
}
stopCluster(cl)
test <- do.call(c, lapply(files, magick::image_read))
test
Related Topics
Existing Function to Combine Standard Deviations in R
Write a File Using 'saverds()' So That It Is Backwards Compatible with Old Versions of R
Error: C Stack Usage Is Too Close to The Limit in R
Get Data Out of a Tcltk Function
Creating a Stacked Bar Chart Centered on Zero Using Ggplot
Combine Two Lists of Dataframes, Dataframe by Dataframe
How to Extract Bold Text from a PDF Using R
How to Add Multiple Columns to a Tibble
Store Output from Gridextra::Grid.Arrange into an Object
Tidyr Separate Column Values into Character and Numeric Using Regex
Ggplot2 Positive and Negative Values Different Color Gradient
R Plotly: Cannot Re-Arrange X-Axis When Axis Type Is Category