gganimate ggplot2 error when using transition_time() after transforming dataset in R… but no error if transformed outside of R

非 Y 不嫁゛ 提交于 2020-06-07 07:23:39

问题


Goal:

Import, transform / prep, and animate a coronavirus dataset from .xlsx using only R.

Text from Reproducible Error:

Error in seq.default(range[1], range[2], length.out = nframes) : 'from' must be a finite number

R Script:

# tidyverse contains ggplot2, dplyr, readr, and tibble libraries
# ggplot2 contains scales library

# install.packages("tidyverse")
library("tidyverse")

# install.packages("RColorBrewer")
library("RColorBrewer")

# install.packages("ggthemes")
library("ggthemes")

# install.packages("gganimate")
library("gganimate")

# install.packages("readxl")
library("readxl")

# create <chr> object to store list of names of 10 most populous TX counties
top10 <- c("Harris", "Dallas", "Tarrant", "Bexar", "Travis", "Collin", "Hidalgo", "El Paso", "Denton", "Fort Bend")

# —1—IMPORT—
# store unmodified .xlsx file from TX Dept. of State Health Services in 'wide' object

    # define object 'wide' to store relevant portions of table from Excel file
    wide <- read_xlsx("Texas COVID-19 Case Count Data by County.xlsx", 
        sheet = NULL, # defaults to first sheet
        skip = 2, # skip first 2 rows
        col_names = TRUE, # 3rd row contains column header names
        n_max = 255) # exclude all irrelevant rows after first 255 records

# —2—TRANSFORM—PREP—
# improve dataset usability by transposing table from wide to long format

    # define 'long' object to modify and store long format table        
    long <- wide %>%
        gather(Date, Cases, -c("County Name", "Population"))
        # creates 'Date' and 'Cases' columns to transpose and store values

# transform / prep the table with a few tweaks

    # changes first column header name from 'County Name' to 'County'
    colnames(long)[colnames(long) == "County Name"] = "County"

    # removes unneeded text from all values in 'Date' column
    long$Date <- gsub("Cases\r\n\r\n", "", long$Date)

    # changes all values in 'Date' column from <chr> to <date> format
    long$Date <- as.Date(long$Date, "%m-%d")

    # changes all values in 'Population' & 'Cases' column from <dbl> to <int> format
    long$Population <- as.integer(long$Population)
    long$Cases <- as.integer(long$Cases)

# add ability to compare % of population infected between counties

    # adds 'Rate' column
    long <- mutate(long, Rate = Cases/Population)
    # note: you can ignore the 'Rate' column because it is not relevant to my question and not relevant to the animation

# —3—ANIMATE—
# animates dataset over time
covid_animation <- long %>% filter(County != "Total" & County %in% top10) %>%
    # sets aesthetic to map 'Date' on x-axis and 'Cases' on y-axis...
    ggplot(aes(Date, Cases, 
        # ...the size of each county's dot proportional to its population...
        size = Population, 
        # ...and a unique color and label for each county's dot
        color = County, label = County)) + 
    # further species that each county's dot should be 70% opaque and that the legend should not be shown because labels are readable
    geom_point(alpha = 0.7, show.legend = FALSE) +
#   scale_colour_manual() + 
#   scale_colour_brewer(palette="Set1") +
    # further specifies that each county's dot should range in size on a 1 to 20 scale
    scale_size(range = c(1, 20)) + 
    # adds a vertical blue line intersecting the x-axis at a value (date) of May 1st, 2020
    geom_vline(xintercept=as.numeric(as.Date("2020-05-01")), color="blue") + 
    # specifies text rules for each county's dot
    geom_text(check_overlap = FALSE, hjust = 0, nudge_x= 6, color="black", size=3) +
    # adds label for vertical blue line
    annotate("text", x = as.Date("2020-05-01"), y = 9000, label = "Texas Re-opens » ", color = "blue", hjust = 1) +     
    # specifies ggplot theme
    theme_minimal() + 
    # specifies text for chart attributes
    labs(title="Total Coronavirus Cases in Texas on: {frame_time}", 
        subtitle="for 10 most populous counties", 
        caption="Dataset Source: Texas Department of State Health Services, May 22, 2020", 
        x="", 
        y="") +
    # potentially where the issue is...animates the plot with gganimate function and produces a frame for each date
    transition_time(Date) + 
    # another gganimate function to smooth the transition between frames
    ease_aes('sine-in')

# saves animation as .gif in your present working directory 
anim_save("covid_animation.gif", covid_animation)

#

#

#

Additional

Information

To Consider:

#

#

#

as_tibble(wide) and as_tibble(long) returns the following, which indicates steps steps #1 (Import) and #2 (Transform/Prep) ran successfully. Based on my research and answers to other StackOverflow questions, I would guess the issue possibly lies with transition_time(Date) when defining covid_animation.

#

#

#

• Animation runs perfectly when I transform / prep the dataset outside of R using OpenRefine and Excel, and when I use a modified version of the R script from above (see below). as_tibble(long) from the script above appears to return the same structure and format as as_tibble(current_date) from the script below — which seems like it rules out any issues with the file itself (Note: You can ignore the difference in the row count — the source file for this happens to be from an earlier date, so there are fewer rows, but the structure is the same.)

# tidyverse contains ggplot2, dplyr, readr, and tibble libraries
# ggplot2 contains scales library

# install.packages("tidyverse")
library("tidyverse")

# install.packages("RColorBrewer")
library("RColorBrewer")

# install.packages("ggthemes")
library("ggthemes")

# install.packages("gganimate")
library("gganimate")

# creates <chr> object to store list of names of 10 most populous TX counties
top10 <- c("Harris", "Dallas", "Tarrant", "Bexar", "Travis", "Collin", "Hidalgo", "El Paso", "Denton", "Fort Bend")

# stores modified file from TX Dept. of State Health Services in 'current_date' object
current_date <- read.table("COVID.csv", sep=",", header=TRUE)
# file has been modified outside of R using OpenRefine and Excel
# file modifications include:
    # changed filename from 'Texas COVID-19 Case Count Data by County.xlsx' to 'COVID.csv'
    # deleted irrelevant headers, footers, rows, and cells
    # changed name of first column header from 'County Name' to 'County'
    # deleted unnecessary text preceding date text from all values in 'Date' column
    # changed format of all values in 'Date' column from <chr> to default <date> format in Excel
    # note: my goal is to do all of the preceding modifications in R rather than using OpenRefine and Excel 

# changes 'Date' column contents from <chr> to <date> just to be sure
current_date <- mutate(current_date, Date = as.Date(Date, "%m/%d"))

# add ability to compare % of population infected between counties

    # adds 'Rate' column
    current_date <- mutate(current_date, Rate = Cases/Population)

# animates dataset over time
covid_animation <- current_date %>% filter(County != "Total" & County %in% top10) %>%
    # sets aesthetic to map 'Date' on x-axis and 'Cases' on y-axis...
    ggplot(aes(Date, Cases, 
        # ...the size of each county's dot proportional to its population...
        size = Population, 
        # ...and a unique color and label for each county's dot
        color = County, label = County)) + 
    # further species that each county's dot should be 70% opaque and that the legend should not be shown because labels are readable
    geom_point(alpha = 0.7, show.legend = FALSE) +
#   scale_colour_manual() + 
#   scale_colour_brewer(palette="Set1") +
    # further specifies that each county's dot should range in size on a 1 to 20 scale
    scale_size(range = c(1, 20)) + 
    # adds a vertical blue line intersecting the x-axis at a value (date) of May 1st, 2020
    geom_vline(xintercept=as.numeric(as.Date("2020-05-01")), color="blue") + 
    # specifies text rules for each county's dot
    geom_text(check_overlap = FALSE, hjust = 0, nudge_x= 6, color="black", size=3) +
    # adds label for vertical blue line
    annotate("text", x = as.Date("2020-05-01"), y = 9000, label = "Texas Re-opens » ", color = "blue", hjust = 1) +     
    # specifies ggplot theme
    theme_minimal() + 
    # specifies text for chart attributes
    labs(title="Total Coronavirus Cases in Texas on: {frame_time}", 
        subtitle="for 10 most populous counties", 
        caption="Dataset Source: Texas Department of State Health Services, May 22, 2020", 
        x="", 
        y="") +
    # potentially where the issue is...animates the plot with gganimate function and produces a frame for each date
    transition_time(Date) + 
    # another gganimate function to smooth the transition between frames
    ease_aes('sine-in')

# saves animation as .gif in your present working directory
anim_save("covid_animation.gif", covid_animation)

回答1:


The problem is with your transformation of the column names into Dates. That seems to introduce NAs into the Dates, and makes the range indeterminate, which gganimate uses for the start and end of the animation.

What worked for me was:

names(wide) = janitor::make_clean_names(names(wide))

and

long <- wide %>%
  gather(Date, Cases, -county_name, -population) %>%
  rename(County = county_name, Population = population) %>%
  mutate(Date = as.Date(str_remove(Date, "cases_"), format = "%m_%d")) %>%
  mutate(Rate = Cases/Population)

long %>% filter(is.na(Date))

Alternatively, you could use str_remove(Date, "\\D+") instead of cleaning up the column names beforehand.



来源:https://stackoverflow.com/questions/62030888/gganimate-ggplot2-error-when-using-transition-time-after-transforming-dataset

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!