我希望对多年来绘制在世界地图(来自 rnaturalearth)上的价值观地图进行动画处理。我已经下载了 rnaturalearth 数据并将其与我的数据集连接起来(三个变量:将其与 rnaturalearth 数据连接的国家/地区代码之一、每个国家/地区的值之一以及年份的值)。我可以正常连接这两个数据集:
baseBorderMap <-
ne_countries(returnclass = 'sf') # Returns world country polygons as sf class
baseBorderMap["51", "iso_a2_eh"] <- "NM" # Renames Namibia country code
baseBorderMap["175", "iso_a2_eh"] <- "XK" # Renames Kosovo country code
aniData <- baseBorderMap %>% right_join(countryYearMam, by = "iso_a2_eh") # Adds counts to map data (maybe something to do with fill needing data with borders?)
aniData <- filter(aniData, !is.na(specimens)) # Remove records with no specimens
我可以使用普通的 ggplot2 函数绘制地图,忽略年份数据:
mammalYear <- ggplot(data = aniData) + # Plots map
geom_sf(data = aniData, lwd = 0) +
geom_sf(data = aniData, aes(fill = log(specimens)), lwd = 0.3) + # Sets fill colour based on specimens from mydata2
#ggtitle("(b)") +
scale_fill_viridis_c() +
theme_bw() +
theme(legend.title = element_blank())
将 gganimate 函数添加到图中并尝试将其可视化或使用
animate()
函数后,我收到错误。
timelapse_mammalYear <- mammalYear +
transition_states(year,
transition_length = 2,
state_length = 1) +
enter_fade() +
exit_fade()
> timelapse_mammalYear
Error in vapply(from, nrow, integer(1)) : values must be length 1,
but FUN(X[[8]]) result is length 0
In addition: Warning message:
In max(area_diff) : no non-missing arguments to max; returning -Inf
此错误是什么意思,如何修改我的数据以正确使用这些函数,以便为我的地图制作动画?
第二次编辑:任何列中都没有 NA。
>dput(head(countryYearMam, 5))
structure(list(iso_a2_eh = c("AD", "AD", "AD", "AD", "AD"), year = c(1930L,
1950L, 1962L, 1965L, 1968L), specimens = c(1L, 12L, 24L, 14L,
3L)), row.names = c(NA, 5L), class = "data.frame")
年份:最小值 = 1793,最大值 = 2020 样本:最小值 = 1,最大值 = 2601
我无法重现您的问题,但潜在原因包括:
gganimate
如果没有您的完整数据集,我无法保证这会解决您的具体问题。但是,这里有一个对您的方法进行了一些改进的代表,“应该”适用于您的实际数据。它使用包含 29,259 行的示例 countryYearMam 数据集。需要考虑的一些要点:
您创建的ne_countries()
ggplot()
aes()
。这是不必要的开销,因此使用 baseBorderMap来代替。
gganimate
已知错误。我不能确定您是否遇到了错误,但是
ne_countries()
过去曾引发过问题
library(rnaturalearth) # 1.0.1
library(dplyr) # 1.1.4
library(sf) # 1.0.15
library(gganimate) # 1.0.8 with ggplot2 3.5.0
# Create world map sf: note addition of scale argument
baseBorderMap <- ne_countries(scale = 50, returnclass = 'sf') %>%
st_set_crs(NA)
# Correct ISO2 country codes: note substitution of iso_a2_eh column
baseBorderMap[which(baseBorderMap$sovereignt == "Namibia"), "iso_a2"] <- "NM"
baseBorderMap[which(baseBorderMap$sovereignt == "Kosovo"), "iso_a2"] <- "XK"
# Simplify geometries for faster plotting
baseBorderMap <- baseBorderMap %>%
st_simplify(preserveTopology = FALSE,
dTolerance = .001)
# Create example countryYearMam df
countryYearMam <- data.frame(matrix(NA, nrow = 0, ncol = 3))
colnames(countryYearMam) <- c("iso_a2", "year", "specimens")
set.seed(1)
for(i in sort(baseBorderMap$iso_a2)) {
j <- sample(30:227, 1)
k <- rep(i, j)
m <- sort(sample(1793:2020, j))
n <- sample(1:2601, j)
tmp <- data.frame(iso_a2 = k, year = m, specimens = n)
countryYearMam <- rbind(countryYearMam, tmp)
}
countryYearMam:
# Join countryYearMam to map sf and filter NAs
aniData <- baseBorderMap %>%
right_join(countryYearMam, by = "iso_a2") %>%
filter(!is.na(specimens)) %>% # included for completeness, no NAs were generated in sample df above
select(continent, iso_a2, year, specimens)
mammalYear <- ggplot() +
geom_sf(data = baseBorderMap, colour = "grey75") +
geom_sf(data = aniData,
aes(fill = log(specimens)),
lwd = 0.3) +
scale_fill_viridis_c() +
theme_bw() +
theme(legend.title = element_blank())
timelapse_mammalYear <- mammalYear +
transition_states(year,
transition_length = 2,
state_length = 1) +
labs(title = "Year: {closest_state}") + # For illustrative purposes
enter_fade() +
exit_fade()
注意此 animate()
脚本在相对低规格的 PC 上运行大约需要 53 分钟
anim <- animate(timelapse_mammalYear,
renderer = gifski_renderer(),
height = 5,
width = 8,
units = "cm",
fps = 1,
duration = 228,
end_pause = 2,
res = 100)
anim