This is my first attempt at a TidyTuesday dataset. TidyTuesday is a weekly data project aimed at the R ecosystem. This week we got the Netflix dataset. Here, I am trying to observe how Netflix shows have expanded beyond border to have movies/TV shows from across the globe.

The Outcome

Netflix got shows from almost all over world. No wonder, everyone finds something for themselves.

Tips i.e. challenges I faced doing it

  • Many shows have been produced from multiple countries. I separate_rows function can be a life-saver in this type of scenario

  • countrycode is a handy little package to clean up all those pesky country naming conventions

  • Spatial objects of sf class are more convenient and memory efficient compared to sp class. Although, gganimate is more open to sp class (I am looking at you transition_reveal). Example- The same animation I tried with sp. It created an object with 400K+ elements. It ran for more than an hour and clogged my 16GB RAM the whole time.

  • In animate function, use bg parameter to match the canvas color to your plot to have a more consistent graphs.

Full Code

### Load libraries

# Data wrangling
library(tidyverse)
library(lubridate)

# Tidy Tuesday datasets
library(tidytuesdayR)

# World maps
library(rnaturalearth)
library(rnaturalearthdata)

# Animation
library(gganimate)


### Get TidyTuesay data

tt_data<-tt_load('2021-04-20')

netflix<-tt_data$netflix_titles



### Clean up an wrangle data with one lengthy pipe

df<-netflix%>%
  mutate(
    date_added_proper=lubridate::mdy(date_added)
  )%>%
  group_by(year=floor_date(date_added_proper,"year"),country)%>%
  summarize(
    count=n()
  )%>%
  ungroup()%>%
  separate_rows(country,sep = ",")%>%
  mutate(
    country=str_trim(country)
  )%>%
  group_by(year,country)%>%
  summarize(
    count=n()
  )%>%
  ungroup()%>%
  filter(country!='NA',country!="" )%>%
  arrange(year,desc(count))%>%
  mutate(
    iso2=countrycode::countryname(country,destination = "iso2c"),
    iso3=countrycode::countryname(country,destination = "iso3c"),
    year=year(year)
  )


### Getting it to maps

# Get map of the world
wmap<-ne_countries(scale = "medium",returnclass = "sf")

# Joining with spatial data
wmap_df<-wmap%>%
  left_join(df,by=c('iso_a3'='iso3'))


# Animation layer - Took a long time to find the most efficient way to animate
wmap_df_anim<-wmap_df%>%
  filter(!is.na(year))%>%
  group_by(iso_a3)%>%
  slice(which.min(year))%>%
  ungroup()%>%
  arrange(year)
 

### Plotting the static map

p<-wmap_df_anim%>%
  ggplot()+
  geom_sf(data=wmap_df%>%select(-year),lwd=0.2)+
  geom_sf(fill='#74020B',lwd=0.2)+
  geom_text(aes(x=75,y=-50,label= paste0(floor(year))),
            size=15,color='#74020B')+
  theme_minimal()+
  labs(
    title = "Netflix shows from Countries",
    caption = "Plot by Saif Kabir Asif | saifkabirasif.com "
  )+
  theme(
    plot.title=element_text(color='#838383',hjust=0.5,size=18,
                            face='bold'),
    plot.caption=element_text(color='gray',face='italic',size=8),
    plot.background = element_rect(fill='black'),
    panel.background = element_rect(fill='black'),
    legend.position = "none",
    axis.title = element_blank(),
    axis.text = element_blank(),
    panel.grid=element_blank()
  )

p


### Animating 

p_anim<-p+transition_time(year)+shadow_mark(exclude_layer = 3)+
  exit_disappear()



animate(p_anim,duration=30 ,
        fps=15,
        start_pause=15,
        end_pause = 15,
        detail=3,
        bg='black',
        type='cairo',
        renderer = gifski_renderer(),
        width=800,
        height=450
)


### Save animation

anim_save(filename = paste0("Netflix_",Sys.Date(),".gif"),animation = last_animation())