Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- library(tidyverse)
- library(gganimate)
- library(tweenr)
- library(stringi)
- library(countrycode)
- #read in data
- #see JBM's original post for links
- data <- read.csv("./city_populations.csv",
- encoding = "UTF-8", stringsAsFactors = FALSE) %>%
- #select out relevant columns
- select(country_id = Country.Code, country = Country.or.area,
- city_id = City.Code, city = Urban.Agglomeration,
- X1950, X1955, X1960, X1965, X1970, X1975, X1980, X1985, X1990,
- X1995, X2000, X2005, X2010, X2015, X2020, X2025, X2030) %>%
- #melt the data to long format
- reshape2::melt(id.vars = c("country_id", "country", "city_id", "city"),
- variable.name = "year", value.name = "population") %>%
- #conver the data into usuable numbers
- mutate(year = as.numeric(gsub("^X", "", year)),
- population = as.numeric(gsub(",", "", population)),
- #convert the text into utf-8 readable
- city = stri_trans_general(city, "latin-ascii")) %>%
- #extract the english names for cities
- mutate(city_name = case_when(
- grepl("\\(", city) ~ str_extract(city, "(?<=\\().+?(?=\\))"),
- grepl("-", city) ~ gsub("-.*", "", city),
- TRUE ~ as.character(city)
- )) %>%
- #group by and find order at any point
- group_by(year) %>%
- arrange(-population) %>%
- mutate(order = row_number()) %>%
- ungroup()
- #get the id data for each unique city
- id_data <- data %>%
- select(city_id, city_name, country_id, country) %>%
- unique() %>%
- #find the continent of each city
- mutate(continent = countrycode(.$country, origin = "country.name", destination = "continent"))
- #the number of frames the output will contain
- frames <- 100
- #use tweenr to manually make the naimation frame data
- frame_data <- data %>%
- group_by(year) %>%
- arrange(-population) %>%
- mutate(order = row_number()) %>%
- #tweenr stuff here
- select(city_id, year, population, order) %>%
- mutate(ease = "linear") %>%
- tween_elements(., "year", "city_id", "ease", nframes= frames) %>%
- #select out columns
- select(population, order, year, .frame, city_id = .group) %>%
- #merge in id data
- merge(., id_data, by = 'city_id') %>%
- #munger population numbers
- mutate(pop = round(population/1000, 2))
- p <- frame_data %>%
- #only want to plot the top 10
- filter(order < 10.8) %>%
- ggplot(aes(y = order, x = pop)) +
- #hack to plot the moving bars
- #from v helpful answer at
- #https://stackoverflow.com/questions/53162821/
- #animated-sorted-bar-chart-with-bars-overtaking-each-other/53163549
- geom_tile(aes(x = pop/2, width = pop, fill = continent),
- alpha = 0.8, colour = "black", height = 0.9) +
- geom_text(aes(label = sprintf("%1.2f",pop)), hjust = 1) +
- geom_text(aes(x = 0, label = paste(city_name, " ")),
- vjust = 0.2, hjust = 1) +
- #add labels to plot
- labs(title='{round(as.numeric(closest_state))}',
- x = "Population (millions)", y = "") +
- #y limits at 0-10.5
- #don't clip as will screw the labels outside the plot
- coord_cartesian(ylim = c(0,10.5), clip = "off") +
- #flip the y axis
- scale_y_reverse(position = "left") +
- #theme stuff
- #taken from same stackoverflow answer
- theme_minimal() +
- theme(plot.title = element_text(hjust = 0, size = 22),
- axis.ticks.y = element_blank(),
- axis.text.y = element_blank(),
- #make sure labels will be visible
- plot.margin = margin(0,0,0,2.5, "cm")) +
- #transition by our calculated year
- transition_states(year, transition_length = 1, state_length = 0) +
- #scale x axis as pop increases
- view_follow(fixed_y = TRUE) +
- #fade as bares enter and exit the plot
- exit_fade() +
- enter_fade()
- #save the gif
- gif <- animate(p, frames)
- anim_save("city_gif.gif", gif)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement