Search code examples
ranimationggplot2data-visualizationgganimate

Formatting dates for {closest_state} output in r (bar chart race)


In this bar chart race, with a Y-m-d date format ("2010-11-30… etc"), the gif (below) runs through the dates fine...

enter image description here

...but when I convert those same dates to a %Y %b format ("2010 Nov… etc"), months are missing throughout the animation, as shown in this second gif, below

enter image description here

Furthermore, I’d ideally like the date to be displayed as %b %Y format (Nov 2010… etc). I've spent weeks trying to sort this out but to no avail. Any help would be appreciated.

Here's the code

df <- read.csv(file="Data/Carmakers market caps monthly.csv")

# Renames headings
df<-rename(df, c(General.Motors = "General Motors", Toyota.Motor = "Toyota Motor"))


meltdf <- melt(df,id="Date")
names(meltdf) <- c("Date", "Company", "Value")


meltdf$Date <- as.Date(meltdf$Date, "%d/%m/%Y")


meltdf$Value <- as.numeric(as.character(meltdf$Value))

meltdf = meltdf %>% 
  group_by(Date)%>%      
  mutate(rank = rank(-Value),
         Value_rel = Value/Value[rank==1],
         Value_lbl = paste0(" ",Value/1000000000)) %>%
  group_by(Company)


meltdf$Value_lbl <- as.numeric(as.character(meltdf$Value_lbl))

meltdf$Value <- as.numeric(as.character(meltdf$Value/1000000000))

meltdf$Value_lbl <- sprintf(meltdf$Value_lbl, fmt = '%#.1f')

strftime(meltdf$Date, format = "%Y %b") -> 
  meltdf$Date


#plotting graph
anim <-ggplot(meltdf,aes(rank,
                            group=Company,
                            fill=as.factor(Company),
                            color=as.factor(Company))) +
  geom_tile(aes(y = Value/2,
                height = Value,
                width = 0.9), alpha = 0.8, color = NA) +
  geom_text(aes(y = 0, label = paste(Company, " ")), vjust = 0.2, hjust = 1)+
  geom_text(aes(y=Value,label = Value_lbl, hjust=0)) +
  coord_flip(clip = "off", expand = TRUE) +
  scale_y_continuous(labels = scales::comma) +
  scale_x_reverse() +
  guides(color = FALSE, fill = FALSE) +
  theme_minimal() +
  theme(
    plot.title=element_text(size=23, hjust=0.5, face="bold", colour="grey", vjust=-1),
    plot.subtitle=element_text(size=18, hjust=0.5, face="italic", color="grey", 
margin = margin(t = 15, r = 0, b = 0, l = 0)),
    plot.caption =element_text(size=8, hjust=0.5, face="italic", color="grey"),
    axis.ticks.y = element_blank(), 
    axis.text.y = element_blank(), 
    plot.margin = margin(1,1,1,2, "cm")) +
  transition_states(states = Date, transition_length = 12, state_length = 1, wrap = FALSE) + 
  ease_aes('cubic-in-out') +
  #view_follow(fixed_x = TRUE) +
  labs(title = 'Largest car companies in the world {closest_state}', 
       subtitle = "Market capitalization",
       caption = "Data source: Refinitiv",
       x="", y="$ billion")

#Create gif
animate(anim, nframes = 400,fps = 8.1,  width = 550, height = 350,
        renderer = gifski_renderer("car_companies_2.gif"), end_pause = 15, start_pause =  25)

And here's a sample of the data that created this chart.

        Date      Tesla Toyota Motor General Motors     Daimler
1 30/11/2010 3295253866 132694537161    51300000000 52944591823
2 31/12/2010 2483798768 136160803584    55290000000 53967411400
3  31/1/2011 2247823894 142843809831    54735000000 56926590672
4  28/2/2011 2277562013 161097730179    52331714768 54401346072
5  31/3/2011 2645556545 138915112426    48429857121 53122249064
6  30/4/2011 2639462630 136650698149    50084659687 55615851126

118  31/8/2020 464338876502 215889700906    42403389651 45497228943
119  30/9/2020 399755220356 214500698099    42346145790 49249966873
120 31/10/2020 367823400433 212138493292    49423051428 47500782647
121 30/11/2020 538028456051 219024834051    62748525184 60564258296
122 31/12/2020 668905110256 250711385128    59599648464 61825906062
123  31/1/2021 668905110256 250711385128    59599648464 61825906062

Solution

  • I have performed all the manipulation in the same pipe using tidyverse functions. You can try :

    library(tidyverse)
    library(gganimate)
    library(lubridate)
    
    df %>%
      pivot_longer(cols = -Date, names_to = 'Company', values_to = 'Value') %>%
      mutate(Date = dmy(Date)) %>%
      group_by(Date)%>%      
      mutate(rank = rank(-Value),
             Value_rel = Value/Value[rank==1],
             Value_lbl = paste0(" ",round(Value/1000000000, 2)), 
             date_format = format(Date, '%b-%Y')) %>%
      arrange(Date) %>%
      mutate(date_format = factor(date_format, unique(date_format))) %>%
      group_by(Company) %>%
      ggplot(aes(rank,
                        group=Company,
                        fill=as.factor(Company),
                        color=as.factor(Company))) +
      geom_tile(aes(y = Value/2,
                    height = Value,
                    width = 0.9), alpha = 0.8, color = NA) +
      geom_text(aes(y = 0, label = paste(Company, " ")), vjust = 0.2, hjust = 1)+
      geom_text(aes(y=Value,label = Value_lbl, hjust=0)) +
      coord_flip(clip = "off", expand = TRUE) +
      scale_y_continuous(labels = scales::comma) +
      scale_x_reverse() +
      guides(color = FALSE, fill = FALSE) +
      theme_minimal() +
      theme(
        plot.title=element_text(size=23, hjust=0.5, face="bold", colour="grey", vjust=-1),
        plot.subtitle=element_text(size=18, hjust=0.5, face="italic", color="grey", 
                                   margin = margin(t = 15, r = 0, b = 0, l = 0)),
        plot.caption =element_text(size=8, hjust=0.5, face="italic", color="grey"),
        axis.ticks.y = element_blank(), 
        axis.text.y = element_blank(), 
        plot.margin = margin(1,1,1,2, "cm")) +
      transition_states(states = date_format, transition_length = 12, state_length = 1, wrap = FALSE) + 
      ease_aes('cubic-in-out') +
      #view_follow(fixed_x = TRUE) +
      labs(title = 'Largest car companies in the world {closest_state}', 
           subtitle = "Market capitalization",
           caption = "Data source: Refinitiv",
           x="", y="$ billion") -> anim
    
    
    animate(anim, nframes = 400,fps = 8.1,  width = 550, height = 350,
            renderer = gifski_renderer("car_companies_2.gif"), end_pause = 15, start_pause =  25)
    

    From the limited data that I could copy from what you have shared the animation looks like this. The important part is that the dates are in order.

    enter image description here

    data

    df <- structure(list(Date = c("30/11/2010", "31/12/2010", "31/1/2011", 
    "28/2/2011", "31/3/2011", "30/4/2011", "31/8/2020", "30/9/2020", 
    "31/10/2020", "30/11/2020", "31/12/2020", "31/1/2021"), Tesla = c(3295253866, 
    2483798768, 2247823894, 2277562013, 2645556545, 2639462630, 464338876502, 
    399755220356, 367823400433, 538028456051, 668905110256, 668905110256
    ), Toyota_Motor = c(132694537161, 136160803584, 142843809831, 
    161097730179, 138915112426, 136650698149, 215889700906, 214500698099, 
    212138493292, 219024834051, 250711385128, 250711385128), General_Motors = c(5.13e+10, 
    5.529e+10, 5.4735e+10, 52331714768, 48429857121, 50084659687, 
    42403389651, 42346145790, 49423051428, 62748525184, 59599648464, 
    59599648464), Daimler = c(52944591823, 53967411400, 56926590672, 
    54401346072, 53122249064, 55615851126, 45497228943, 49249966873, 
    47500782647, 60564258296, 61825906062, 61825906062)), 
    class = "data.frame", row.names = c(NA, -12L))