以前有效的代码中出现“替换有 x 行”错误(geom_sf/gganimate/shadow_mark)

问题描述 投票:0回答:1

我有多年来在不同地点观察物种的数据。有些年份没有任何数据。我想创建一个动画地图,其中包括没有数据的年份,并且我成功地做到了这一点,但它只是暂时出现。

这里有一些代表:

library(sf)
library(ggplot2)
library(gganimate)
library(transformr)
library(tidyr)

rb <- data.frame(YEAR = c(1995, 2000, 2000, 2001, 2002, 2002, 2002, 2004), 
                 TOTAL = c(5, 10, 8, 14, 15, 12, 16, 15),
                 LONG = c(runif(8, -80, -78)),
                 LAT = c(runif(8, 38, 40)))

用我的坐标范围内的一组随机坐标填充缺失的年份:

rb.zero.df <- data.frame(rb %>% 
                           complete(YEAR = full_seq(1995:2004, 1), 
                                    fill = list(LONG = -78.3893, 
                                                LAT = 39.63938, 
                                                TOTAL = 0)))

rb.zero <- st_as_sf(rb.zero.df, coords = c("LONG", "LAT"), crs = 4326)

然后使用

ifelse
代替
alpha
aes
中的
shadow_mark
以确保零点不会出现:

rb.zero.map <- ggplot() +
  geom_sf(data = rb.zero, aes(size = TOTAL, alpha = ifelse(TOTAL == 0, 0, 1))) +
  scale_alpha(range = c(0,1)) +
  guides(alpha = "none") +
  transition_states(YEAR, transition_length = 0, state_length = 1) +
  ggtitle("{closest_state}") +
  shadow_mark(alpha = ifelse(rb.zero$TOTAL == 0, 0, 0.25))
animate(rb.zero.map)

这曾经有效,但现在会产生此错误:

Error in `[[<-.data.frame`(`*tmp*`, i, value = c(0.25, 0, 0, 0, 0, 0.25,  : 
  replacement has 13 rows, data has 12

我不知道如何在这种情况下解释此错误。

如果我从

ifelse
中取出
shadow_mark
,代码就可以工作。

我的会议信息:

R version 4.3.2 (2023-10-31)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.3.1

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/New_York
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] transformr_0.1.3      gifski_1.12.0-2       gganimate_1.0.7       tidyr_1.3.0          
 [5] viridis_0.6.4         viridisLite_0.4.2     spData_2.3.0          dplyr_1.1.4          
 [9] terra_1.7-65          sf_1.0-15             ggplot2_3.4.4         leaflet.extras2_1.2.2
[13] leaflet_2.2.1         tmap_3.99.9000       

loaded via a namespace (and not attached):
 [1] DBI_1.2.1               gridExtra_2.3           tmaptools_3.1-1         remotes_2.4.2.1        
 [5] rlang_1.1.3             magrittr_2.0.3          e1071_1.7-14            compiler_4.3.2         
 [9] mgcv_1.9-0              png_0.1-8               vctrs_0.6.5             stringr_1.5.1          
[13] profvis_0.3.8           pkgconfig_2.0.3         crayon_1.5.2            fastmap_1.1.1          
[17] ellipsis_0.3.2          labeling_0.4.3          lwgeom_0.2-13           leafem_0.2.3           
[21] utf8_1.2.4              promises_1.2.1          sessioninfo_1.2.2       purrr_1.0.2            
[25] cachem_1.0.8            progress_1.2.3          later_1.3.2             tweenr_2.0.2           
[29] parallel_4.3.2          prettyunits_1.2.0       R6_2.5.1                stringi_1.8.3          
[33] RColorBrewer_1.1-3      pkgload_1.3.4           stars_0.6-4             Rcpp_1.0.12            
[37] usethis_2.2.2           base64enc_0.1-3         leaflet.providers_2.0.0 Matrix_1.6-1.1         
[41] httpuv_1.6.13           splines_4.3.2           tidyselect_1.2.0        rstudioapi_0.15.0      
[45] dichromat_2.0-0.1       abind_1.4-5             codetools_0.2-19        miniUI_0.1.1.1         
[49] pkgbuild_1.4.3          lattice_0.21-9          tibble_3.2.1            leafsync_0.1.0         
[53] plyr_1.8.9              shiny_1.8.0             withr_3.0.0             units_0.8-5            
[57] proxy_0.4-27            urlchecker_1.0.1        lpSolve_5.6.20          pillar_1.9.0           
[61] KernSmooth_2.23-22      generics_0.1.3          sp_2.1-2                hms_1.1.3              
[65] munsell_0.5.0           scales_1.3.0            xtable_1.8-4            class_7.3-22           
[69] glue_1.7.0              tools_4.3.2             leaflegend_1.2.0        data.table_1.14.10     
[73] fs_1.6.3                XML_3.99-0.16.1         grid_4.3.2              crosstalk_1.2.1        
[77] devtools_2.4.5          colorspace_2.1-0        nlme_3.1-163            cols4all_0.7           
[81] raster_3.6-26           cli_3.6.2               fansi_1.0.6             gtable_0.3.4           
[85] digest_0.6.34           widgetframe_0.3.1       classInt_0.4-10         htmlwidgets_1.6.4      
[89] farver_2.1.1            memoise_2.0.1           htmltools_0.5.7         lifecycle_1.0.4        
[93] mime_0.12 

我不知道为什么这段代码以前有效而现在不起作用 - 数据和代码是相同的。我很感激对此和/或缺失年份问题的替代解决方案的想法。谢谢!

r alpha gganimate geom-sf
1个回答
0
投票

TL;博士

使用

shadow_mark(alpha = alpha / 4)

而不是

shadow_mark(alpha = ifelse(rb.zero$TOTAL == 0, 0, 0.25))

前言

当我尝试你的例子时,我得到了一个不同的错误:

Error: arguments have different crs

但是这似乎是 gganimate 中的一个错误,临时修复是完全删除

crs

问题说明

对于您手头的问题,您没有按照预期的方式使用

shadow_mark
。如果您调试
train
(
ShadowMark
) 的
debug(get("train", ShadowMark))
函数,您将看到传递给
shadow_mark
的任何内容都将在当前动画步骤中显示的数据切片的上下文中进行评估。

我对

gganimate
的内部结构并不深入,但显然他们将每个切片的原始数据分开并发挥了他们的魔力。

重要的是,在某个步骤中,“当前”数据只是整个数据集(富含美学数据)的子集,也就是说,它仅包含原始行的子集

在这种情况下,评估

ifelse(rb.zero$TOTAL == 0, 0, 0.25))
没有意义,因为它总是评估长度为
nrow(rb.zero.df)
(=13) 的向量,这可能会导致您看到的错误,特别是当当前数据切片仅为 12 时行长(而
ifelse(rb.zero$TOTAL == 0, 0, 0.25)
always 13 个元素长)。


NB. 意思是,对于某些组合,您不会立即看到错误,因为

R's
回收规则,只有当长度不兼容时(通常不是彼此的倍数)。


解决方案

话虽如此,

shadow_mark
的使用方式是提供
aesthetics
的名称作为参数。这是可行的,因为
shadow_mark
使用 quosures,即它稍后在正确的上下文中评估其参数。上下文是之前提到的数据切片,在您的情况下有一个
alpha
插槽。

长话短说,你应该像这样创建你的情节:

## drop crs b/c of unfixed bug
rb.zero <- st_as_sf(rb.zero.df, coords = c("LONG", "LAT")) 

rb.zero.map <- ggplot() +
  geom_sf(data = rb.zero, aes(size = TOTAL, alpha = ifelse(TOTAL == 0, 0, 1))) +
  scale_alpha(range = c(0,1)) +
  guides(alpha = "none") +
  transition_states(YEAR, transition_length = 0, state_length = 1) +
  ggtitle("{closest_state}") +
  ### use alpha, gganimate knows how to evaluate it properly
  shadow_mark(alpha = alpha / 4)
animate(rb.zero.map)


© www.soinside.com 2019 - 2024. All rights reserved.