Можно ли анимировать заливку полигонов с помощью gganimate в R? - PullRequest
0 голосов
/ 04 марта 2019

У меня есть данные на уровне округа, записывающие год, когда инвазивные вредные насекомые были впервые обнаружены в этом округе в период между 2002 и 2018 годами. Я создал карту, используя ggplot2, и пакет карт, который заполняет полигоны округа цветом в соответствии с годом, в котором был нанесен вредный организм.был обнаружен.

** Есть ли способ использовать пакет gganimate для анимации этой карты с заполнением первого кадра только полигонами с датой обнаружения 2002 г., полигонов заполнения второго кадра?с датой обнаружения 2003 или более ранней (так 2002 и 2003), третьим кадром для дат обнаружения 2004 или более ранней (2002, 2003, 2004) и т. д.?** Уточнение: мне бы хотелось, чтобы все полигоны округов всегда были видны и изначально были заполнены белым, а каждый кадр анимации добавляет графы заливок в зависимости от года обнаружения.

Я пробовалиспользуя transition_reveal(data$detect_year) со статическим графиком, но получаю ошибку, что «вдоль данных должны быть либо целые числа, либо числа, POSIXct, Date, difftime, orhms».

Вот некоторый код для воспроизводимого примера:

library(dplyr)
library(purrr)
library(maps)
library(ggplot2)
library(gganimate)
# Reproducible example
set.seed(42)
map_df <- map_data("county") %>% 
   filter(region == "minnesota")
map_df$detection_year <- NA
# Add random detection year to each county
years <- 2002:2006
map_list <- split(map_df, f = map_df$subregion)
map_list <- map(map_list, function(.x) {
   .x$detection_years <- mutate(.x, detection_years = sample(years, 1))
})
# collapse list back to data frame
map_df <- bind_rows(map_list)
map_df$detection_years <- as.factor(map_df$detection_years)

# Make plot
static_plot <- ggplot(map_df,
                      aes(x = long,
                          y = lat,
                          group = group)) +
   geom_polygon(data = map_df, color = "black", aes(fill = detection_years)) +
   scale_fill_manual(values = terrain.colors(n = length(unique(map_df$detection_years))),
                     name = "Year EAB First Detected") +
   theme_void() +
   coord_fixed(1.3)

animate_plot <- static_plot +
   transition_reveal(detection_years)

Если это возможно сделать с помощью gganimate, я бы хотел, но я также открыт для других решений, если у кого-то есть идеи.

Ответы [ 2 ]

0 голосов
/ 06 марта 2019

Получив ответ от @RLave, который почти сделал то, что я хотел, и потратив немного времени на документацию, я смог найти способ сделать то, что я хочу.Кажется, он не очень чистый, но он работает.

По сути, я создавал копию своего фрейма данных для каждого года, в котором был необходим кадр в анимации.Затем для каждого года обнаружения, который я хотел анимировать, я редактировал переменную detection_year в этой копии фрейма данных таким образом, чтобы любой округ, который обнаружил в интересующем году или ранее, сохранил свои значения, а любой округ, который не обнаружилвсе же был преобразован в значение, которое я изобразил белым.Это позволило убедиться, что все графства всегда были построены.Затем мне нужно было использовать transition_manual вместе с уникальным идентификатором, который я дал каждой копии исходного кадра данных, чтобы определить порядок анимации.

library(dplyr)
library(purrr)
library(maps)
library(ggplot2)
library(gganimate)
# Reproducible example
set.seed(42)
years <- 2002:2006

map_df <- map_data("county") %>% 
   filter(region == "minnesota")

map_df <- map_df %>% 
   group_by(subregion) %>% 
   mutate(detection_year = sample(years,1))

animate_data <- data.frame()
for(i in 2002:2006){
   temp_dat <- map_df %>% 
      mutate(detection_year = as.numeric(as.character(detection_year))) %>% 
      mutate(detection_year = case_when(
         detection_year <= i ~ detection_year,
         detection_year > i ~ 2001
      ),
      animate_id = i - 2001
      )
   animate_data <- bind_rows(animate_data, temp_dat)
}

animate_data$detection_year <- as.factor(as.character(animate_data$detection_year))

# Make plot
static_plot <- ggplot(animate_data,
                      aes(x = long,
                          y = lat,
                          group = group)) +
   geom_polygon(data = animate_data, color = "black", aes(fill = detection_year)) +
   scale_fill_manual(values = c("white",
                                terrain.colors(n = 5)),
                     name = "Year First Detected") +
   theme_void() +
   coord_fixed(1.3) #+
   facet_wrap(~animate_id)

animate_plot <- static_plot +
   transition_manual(frames = animate_id)
animate_plot

0 голосов
/ 05 марта 2019

Возможно это, но я не уверен, что это ожидаемый результат.

Я изменил ваш код, вероятно, вам не нужно split.Я использовал group_by, чтобы назначить год для каждого региона.

set.seed(42)
years <- 2002:2006

map_df <- map_data("county") %>% 
  filter(region == "minnesota")

map_df <- map_df %>% 
  group_by(subregion) %>% 
  mutate(detection_year = sample(years,1))

Для перехода необходимо определить id, здесь то же самое, что и группировка (subregion или group) иправильный формат даты для переменной перехода (along) (я использовал lubridate::year())

# Make plot
static_plot <- ggplot(map_df,
                      aes(x = long,
                          y = lat,
                          group = group)) +
  geom_polygon(color = "black", aes(fill = as.factor(detection_year))) +
  scale_fill_manual(values = terrain.colors(n = length(unique(map_df$detection_year))),
                    name = "Year EAB First Detected") +
  theme_void() +
  coord_fixed(1.3)

animate_plot <- static_plot +
  transition_reveal(subregion, # same as the group variable
                    lubridate::year(paste0(detection_year, "-01-01"))) # move along years

enter image description here

Делает ли это это для вас

...