rdplyrgganimate

Filter data frame by multiple conditions stored in one string, using gganimate


I am trying to create a scatter plot animation using gganimate by creating a shifting window that filters data points. I have used the transition_filter function to create the animation. Instead of manually writing out all of the filtering conditions, I created a string of all the conditions in a loop, with the intention of converting it into something recognizable by transition_filter.

Here is my code:

require(ggplot2)
require(gganimate)

df <- data.frame(x = runif(1000), y = runif(1000), f = runif(1000))

conds <- ""

for (i in 1:30) {
  conds <- paste0(conds, 0.5 + 0.01 * i, " <= f & f < ", 0.7 + 0.01 * i, ", ")
}

ggplot(df) + geom_point(aes(x = x, y = y)) +
  transition_filter(transition_length = 2,
                    filter_length = 1,
                    !!rlang::parse_expr(conds)) + 
  enter_fade() + 
  ggtitle('{closest_expression}')

Despite my efforts, I keep receiving an error message:

Error in parse(text = x, keep.source = FALSE) (temp.R#802): <text>:1:21: unexpected ','
1: 0.51 >= f & f > 0.71,
                        ^

How can I convert the string of conditions into something that transition_filter or dplyr::filter can recognize?


Solution

  • First you have to create a vector of conditions not one long string. Second, as we are now have a vector use rlang::parse_exprs. Finally, use the unsplice operator !!! to pass your filter conditions to transition_filter:

    Note: Check your filter conditions. Your conditions return an empty dataset, e.g. for i = 1 I use f >= 0.51 & f < 0.71 while in your code it's 0.51 >= f & f > .71 which is FALSE for all f.

    library(ggplot2)
    library(gganimate)
    
    set.seed(123)
    
    df <- data.frame(x = runif(100), y = runif(100), f = runif(100))
    
    n <- 30
    conds <- paste0("f >= ", 0.5 + 0.01 * seq(n), " & f < ", 0.7 + 0.01 * seq(n))
    
    ggplot(df) +
      geom_point(aes(x = x, y = y)) +
      transition_filter(
        transition_length = 2,
        filter_length = 1,
        !!!rlang::parse_exprs(conds)
      ) +
      enter_fade() +
      ggtitle(
        "Filter: {closest_filter}",
        subtitle = "{closest_expression}"
      )