I have another issue working with the same dataset as #429. As I mentioned, after applying the workaround for "filled" data that I described there, my animation rendered. However, I needed to construct more descriptive labels for each state, so I created a new variable that was a label based on the values of the SES-category variable (included in reprex below).
When the class of this variable is character, the animation works fine. But the order of states is incorrect - it goes from percentile 1 to 5 to percentile 11 to 15, rather than to 6-10 as it should. Arranging the table before creating the animation also has no impact on the order of states in the animation:
(this is a testing example so it moves quite fast because of having very few frames. The full gif is too big to upload here).
To fix this, I tried turning it into an ordered factor, but when I pass the variable as a factor to SES states the animation fails, with the same error I was receiving in issue #429.
Error in tween_state(as.data.frame(full_set$from), as.data.frame(full_set$to), :
identical(classes, col_classes(to)) is not TRUE
So overall, I can't order the states when states is a character variable, and it fails to animate when it is a factor?
Here is the reprex:
# !usr/bin/env Rscript
# Author: Saeesh Mangwani
# Date: 2021-03-19
# Description: Animation issues for reprex
# ==== Loading libraries ====
library(tidyverse)
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1
library(ragg)
library(reprex)
library(gganimate)
# Script where I define some helper functions for working with my data, including
# the custom theme function I use later (theme_accra)
source("C:/Users/saees/codeProjects/RProjects/accra/accra_viz.R")
#>
#> Attaching package: 'rlang'
#> The following objects are masked from 'package:purrr':
#>
#> %@%, as_function, flatten, flatten_chr, flatten_dbl, flatten_int,
#> flatten_lgl, flatten_raw, invoke, list_along, modify, prepend,
#> splice
# Adding a showtext font 'lmroman
library(showtext)
#> Loading required package: sysfonts
#> Loading required package: showtextdb
font_paths(new = "C:/Users/saees/Appdata/Local/Microsoft/Windows/Fonts")
#> [1] "C:\\Users\\saees\\AppData\\Local\\Microsoft\\Windows\\Fonts"
#> [2] "C:\\Windows\\Fonts"
font_add(family = "lmroman", regular = "lmroman10-regular.otf")
showtext_auto()
# ==== Reading data ====
# Reading the census and the shapefile, ensuring only relevant variables are selected
census <- census <- read_csv("C:/Users/saees/codeProjects/RProjects/accra/data/gama/gama20210216_filled.csv")
#>
#> -- Column specification --------------------------------------------------------
#> cols(
#> .default = col_double()
#> )
#> i Use `spec()` for the full column specifications.
accra <- read_sf("C:/Users/saees/codeProjects/RProjects/accra/data/shp/GAMA_20200420.shp", query = "SELECT ea_code9ch FROM GAMA_20200420")
# Turning the eacode variable in the census dataset to a string to make joining with the shapefile easier
census <- census %>%
mutate(ea_code9ch = str_pad(ea_code9ch, width = 9, side = 'left', pad = '0'))
# Joining data to shapefile
gama <- census %>%
inner_join(accra, by = c("ea_code9ch" = "ea_code9ch")) %>%
st_as_sf()
# Removing the extra dataset to only keep gama
rm(list = c('census', 'accra'))
# ==== Adding more descriptive labels to the SES cat variable ====
# THe number of percentile groups in the dataset
n_percentiles <- 20
# First splitting a vector of 100 into the number of groups defined above to mimic
# the percentile distribution of SES_cat
percentiles <- split(1:100, sort(rep_len(1:n_percentiles, 100)))
# Turning each list into only a min and max, as that is all we need to construct a
# range label
percentiles <- map(percentiles, ~{ c(min(.x), max(.x))})
# Getting the SES-categories as a vector, and creating a parallel vector of
# labelled names based on it
percentile_labels <- map_chr(as.character(gama$SES_cat_g3), ~ {
case_when(
# If the category is not 30 or 40, constructing the label from the right
# percentile bin
!(.x %in% c(30, 40)) ~ paste0(percentiles[[.x]][1], "-", percentiles[[.x]][2], "th Percentile"),
# Otherwise using default labels
.x == 30 ~ "Students & university residents",
.x == 40 ~ "Homeless and outdoor sleeper residents"
)
})
# Getting a correctly ordered factor for the cat labels, based on the order of the
# categorical variable and passing this as the new label variable
gama$SES_cat_labels <- fct_reorder(percentile_labels, as.numeric(gama$SES_cat_g3))
# Illustrating the outcome of this
gama %>%
arrange(ea_code9ch, as.numeric(SES_cat_g3)) %>%
select(SES_cat_g3, SES_cat_labels) %>%
head(n = 10)
#> Simple feature collection with 10 features and 2 fields
#> geometry type: MULTIPOLYGON
#> dimension: XY
#> bbox: xmin: -0.3847607 ymin: 5.484172 xmax: -0.3786746 ymax: 5.488131
#> geographic CRS: WGS 84
#> # A tibble: 10 x 3
#> SES_cat_g3 SES_cat_labels geometry
#> <dbl> <fct> <MULTIPOLYGON [°]>
#> 1 1 1-5th Percentile (((-0.3786746 5.486327, -0.3788675 5.486252, -0.~
#> 2 2 6-10th Percenti~ (((-0.3786746 5.486327, -0.3788675 5.486252, -0.~
#> 3 3 11-15th Percent~ (((-0.3786746 5.486327, -0.3788675 5.486252, -0.~
#> 4 4 16-20th Percent~ (((-0.3786746 5.486327, -0.3788675 5.486252, -0.~
#> 5 5 21-25th Percent~ (((-0.3786746 5.486327, -0.3788675 5.486252, -0.~
#> 6 6 26-30th Percent~ (((-0.3786746 5.486327, -0.3788675 5.486252, -0.~
#> 7 7 31-35th Percent~ (((-0.3786746 5.486327, -0.3788675 5.486252, -0.~
#> 8 8 36-40th Percent~ (((-0.3786746 5.486327, -0.3788675 5.486252, -0.~
#> 9 9 41-45th Percent~ (((-0.3786746 5.486327, -0.3788675 5.486252, -0.~
#> 10 10 46-50th Percent~ (((-0.3786746 5.486327, -0.3788675 5.486252, -0.~
# ==== Issue with not rendering when states variable is a factor ====
p <- gama %>%
mutate(group = 1L) %>%
# Removing some EAs and district to only map the relevant area
filter(district_code %in% c(10304)) %>%
filter(!(SES_cat_g3 %in% c(30, 40))) %>%
# Arranging the data seems to have no impact?
arrange(ea_code9ch, as.numeric(SES_cat_g3)) %>%
# If I turn the variable back to character, the animation renders. Otherwise, it fails:
# mutate(SES_cat_labels = as.character(SES_cat_labels)) %>%
# Enumeration area code, group, median logged income, socio-economic category
dplyr::select(ea_code9ch, group, ni_num, SES_cat_labels) %>%
# Turning population data to a factor to plot it using quintile breaks
mutate(ni_num = cut(ni_num, breaks = quantile(gama$medlec, probs = seq(0,1,0.2), na.rm = T), ordered_result = T)) %>%
# Ensuring it is a factor
mutate(ni_num = as_factor(ni_num)) %>%
# Plotting
ggplot() +
geom_sf(aes(fill = ni_num, group = group), colour = "white", size = 0.2) +
scale_fill_brewer(palette = "OrRd") +
labs(title = "Median Income: SES Category {closest_frame}",
subtitle = "Greater Accra Metropolitan Area",
fill = "Median Income\n(Quantiles)",
x = NULL,
y = NULL) +
# Custom theme that I've made, only edits layout variables like font panel grid, legend, etc.
theme_accra(theme_font = "lmroman", tscale = 7)
# Transition states (the SES cat variable is grouping factor that defines different socio-economic categories).
anim <- p + transition_states(SES_cat_labels, transition_length = 2, state_length = 2, wrap = T) + exit_fade()
# Using a small number of frames to test whether it's working
anim_save("popAnim-GAMA.gif",
animation = anim,
device = "ragg_png", width = 6.5, height = 5.5,
scaling = 0.45, units = "in", res = 300,
nframes = 20, fps = 10)
#> Error in tween_state(as.data.frame(full_set$from), as.data.frame(full_set$to), : identical(classes, col_classes(to)) is not TRUE
Hello,
I have another issue working with the same dataset as #429. As I mentioned, after applying the workaround for "filled" data that I described there, my animation rendered. However, I needed to construct more descriptive labels for each state, so I created a new variable that was a label based on the values of the SES-category variable (included in reprex below).
When the class of this variable is
character
, the animation works fine. But the order of states is incorrect - it goes from percentile 1 to 5 to percentile 11 to 15, rather than to 6-10 as it should. Arranging the table before creating the animation also has no impact on the order of states in the animation:(this is a testing example so it moves quite fast because of having very few frames. The full gif is too big to upload here).
To fix this, I tried turning it into an ordered factor, but when I pass the variable as a factor to SES states the animation fails, with the same error I was receiving in issue #429.
So overall, I can't order the states when
states
is a character variable, and it fails to animate when it is a factor?Here is the reprex:
And my session information: