3

I'm trying the gganimate package for the first time and run into a problem with the handling of missing values (NA). I apologize if my question is trivial but I couldn't find any solution.

Here is a reproducible example of what I'm trying to do:

# Load libraries:
library(ggplot2)
library(gganimate)
library(dplyr)
library(tidyr)  

# Create some data
  ## Monthly sales are in 100:1000
  ## Expected sales are 400/month, increasing by 5% every year
set.seed(123)
df <- data_frame(Year = rep(2015:2018, each=12),
                 Month = rep(1:12, 4),
                 Sales = unlist(lapply(1:4, 
                           function(x){cumsum(sample(100:1000, 12))})),
                 Expected = unlist(lapply(1:4, 
                           function(x){cumsum(rep(400*1.05^(x-1),12))})))

# gganimate works fine here:
df %>% 
    tidyr::gather("Type", "value", Sales:Expected) %>%
    ggplot(aes(Month, value, col=Type)) +
        geom_point() +
        geom_line() +
        gganimate::transition_time(Year)

# Now data for the end of Year 2018 are missing:
df[df$Year==2018 & df$Month %in% 9:12,"Sales"] = NA

# Plotting with ggplot2 works (and gives a warning about missing values):
df %>% 
    tidyr::gather("Type", "value", Sales:Expected) %>%
    dplyr::filter(Year == "2018") %>%
    ggplot(aes(Month, value, col=Type)) +
        geom_point() +
        geom_line()

# But gganimate fails
df %>% 
    tidyr::gather("Type", "value", Sales:Expected) %>%
    ggplot(aes(Month, value, col=Type)) +
        geom_point() +
        geom_line() +
        gganimate::transition_time(Year) 

# I get the following error: 
## Error in rep(seq_len(nrow(polygon)), splits + 1) : incorrect 'times' argument

I tried to play with the enter_() / exit_() functions of gganimate but without success.
Thank you for your help.

EDIT: (using the suggestion of MattL)
This works:

df %>% 
    # filter(!is.na(Sales)) %>% ##Proposed by Matt L but removes Expected values too
    gather("Type", "value",Sales:Expected) %>%
    filter(!is.na(value)) %>% ## Remove NA values
    ggplot(aes(Month, value, col=Type)) +
        geom_point() +
        geom_line() +
        labs(title = "Year: {frame_time}") + ## Add title
        gganimate::transition_time(Year) +
        gganimate::exit_disappear(early=TRUE) ## Removes 2017 points appearing in Year 2018

I still have the feeling that gganimate should be able to handle these NA values like ggplot does though. Thanks!

nick
  • 1,090
  • 1
  • 11
  • 24
Pascal Martin
  • 311
  • 2
  • 9
  • 1
    If you just add `filter(!is.na(Sales)) %>% ` before you pipe to `gather` and then `ggplot` command it should work. – Matt L. Aug 18 '18 at 15:56
  • 1
    Thank you for your answer. Yes that does work. The issue with this solution is that it also removes the values for "Expected". However, applying `filter(!is.na(value))` after `gather` works fine too. Also, in the animation, the points corresponding to the values for Sept-Dec 2017 (Sales and Expected) remain in 2018. I solved this using: `+ gganimate::exit_disappear(early=TRUE)`. I edit my question with this solution. Thanks again. – Pascal Martin Aug 18 '18 at 16:32

1 Answers1

1

Filter out the missing values before "piping" to the ggplot function:

df %>% 
    filter(!is.na(Sales)) %>% 
    tidyr::gather("Type", "value", Sales:Expected) %>%
    ggplot(aes(Month, value, col=Type)) +
        geom_point() +
        geom_line() +
        gganimate::transition_time(Year) 
Matt L.
  • 2,753
  • 13
  • 22