Ошибка gganimate ggplot2 при использовании transition_time () после преобразования набора данных в R ... но без ошибок при преобразовании вне R - PullRequest
0 голосов
/ 26 мая 2020

Цель:

Импорт, преобразование / подготовка и анимация набора данных коронавируса из .xlsx, используя только R.

Текст из воспроизводимой ошибки:

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)

#

#

#

Дополнительно

Информация

Для рассмотрения:

#

#

#

as_tibble(wide) и as_tibble(long) возвращают следующее, которое указывает, что шаги №1 (Импорт) и №2 (Преобразование / Подготовка) выполнены успешно. Основываясь на моем исследовании и ответах на другие вопросы StackOverflow, я предполагаю, что проблема, возможно, связана с transition_time(Date) при определении covid_animation.

enter image description here

#

#

#

• Анимация работает отлично, когда я трансформирую / подготавливаю набор данных за пределами R с использованием OpenRefine и Excel, а также когда я использую модифицированную версию сценария R сверху (см. Ниже). as_tibble(long) из приведенного выше сценария, похоже, возвращает ту же структуру и формат, что и as_tibble(current_date) из приведенного ниже сценария, что, похоже, исключает любые проблемы с самим файлом (Примечание: вы можете игнорировать разницу в количестве строк - исходный файл для этого оказался более ранним, поэтому строк меньше, но структура такая же.)

enter image description here

enter image description here

enter image description here

# 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 Ответ

1 голос
/ 27 мая 2020

Проблема в том, что вы преобразовали имена столбцов в даты. Похоже, это вводит NA в даты и делает неопределенным диапазон, который gganimate использует для начала и конца анимации.

Что сработало для меня:

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

и

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))

В качестве альтернативы вы можете использовать str_remove(Date, "\\D+") вместо предварительной очистки имен столбцов.

...