将group_by%>%summary%>%mutate与sf对象一起使用的适当过程

问题描述

我正在开发一种工作流处理脚本,用于处理R中的sf个对象。sf是对象的简单要素类,它提供了一种处理tidyverse中空间数据的方法。但是,我在使用存储为sf的数据执行标准group_by()%>%summary()%>%mutate()进程时遇到了严重的困难。我遇到一个问题,其中group_by()%>%summary()在对象转换为数据框后可用于该对象,但不能用作sf

基本上,我正在尝试按较高级别的地理位置对较低级别的地理位置进行分组,并输出汇总变量。然后,我需要在新的汇总sf数据对象中对变量进行突变,该数据对象可计算多个变量的总和并除以另一个变量。对于sf对象,此最后一个操作将引发错误“ x'x'必须是数字”,但是相同的操作适用于具有相同数据的数据帧(无geography)。而且我已经验证了传递给rowSums函数的所有变量的x 是数值。

下面的完整说明。在第一个示例中,您看到在示例数据的sf版本上操作失败。在第二个示例中,在as.data.frame()函数之前传递了separate(),该过程成功了,但这消除了对我的分析至关重要的地理位置。

谢谢,全部!

library(sf)
#> Warning: package 'sf' was built under R version 4.0.2
#> Linking to GEOS 3.8.1,GDAL 3.1.1,PROJ 6.3.1
library(tidyverse)
#> Warning: package 'ggplot2' was built under R version 4.0.2
#> Warning: package 'tibble' was built under R version 4.0.2
#> Warning: package 'tidyr' was built under R version 4.0.2
#> Warning: package 'dplyr' was built under R version 4.0.2
library(dplyr)
library(spdep)
#> Loading required package: sp
#> Loading required package: spData
#> To access larger datasets in this package,install the spDataLarge
#> package with: `install.packages('spDataLarge',#> repos='https://Nowosad.github.io/drat/',type='source')`
library(stringi)
#> Warning: package 'stringi' was built under R version 4.0.2

nc <- st_read(system.file("shapes/sids.shp",package="spData")[1],quiet=TRUE)
st_crs(nc) <- "+proj=longlat +datum=NAD27"
row.names(nc) <- as.character(nc$FIPSNO)

names(nc)
#>  [1] "CNTY_ID"   "AREA"      "PERIMETER" "CNTY_"     "NAME"      "FIPS"     
#>  [7] "FIPSNO"    "CRESS_ID"  "BIR74"     "SID74"     "NWBIR74"   "BIR79"    
#> [13] "SID79"     "NWBIR79"   "east"      "north"     "x"         "y"        
#> [19] "lon"       "lat"       "L_id"      "M_id"      "geometry"

nc %>% 
  separate(CNTY_ID,into = c("ID1","ID2"),sep = 2,remove = FALSE) %>% 
  group_by(ID1) %>% 
  dplyr::summarize(AREA = sum(AREA,na.rm = TRUE),BIR74 = sum(BIR74,SID74 = sum(SID74,NWBIR74 = sum(NWBIR74,na.rm = TRUE)
                   ) %>% 
  mutate(stupid_var = rowSums(dplyr::select(.,'SID74':'NWBIR74'))/BIR74)
#> `summarise()` ungrouping output (override with `.groups` argument)
#> Error: Problem with `mutate()` input `stupid_var`.
#> x 'x' must be numeric
#> ℹ Input `stupid_var` is `rowSums(dplyr::select(.,"SID74":"NWBIR74"))/BIR74`.

class(nc$SID74)
#> [1] "numeric"
class(nc$NWBIR74)
#> [1] "numeric"
class(nc$BIR74)
#> [1] "numeric"

nc %>% 
  as.data.frame() %>% 
  separate(CNTY_ID,na.rm = TRUE)
  ) %>% 
  mutate(stupid_var = rowSums(dplyr::select(.,'SID74':'NWBIR74'))/BIR74)
#> `summarise()` ungrouping output (override with `.groups` argument)
#> # A tibble: 5 x 6
#>   ID1    AREA  BIR74 SID74 NWBIR74 stupid_var
#>   <chr> <dbl>  <dbl> <dbl>   <dbl>      <dbl>
#> 1 18    2.53   36723    89   12788      0.351
#> 2 19    4.03  132525   203   38392      0.291
#> 3 20    3.94  111540   237   35281      0.318
#> 4 21    1.63   38117   106   14915      0.394
#> 5 22    0.494  11057    32    3723      0.340

reprex package(v0.3.0)于2020-09-21创建

解决方法

我对以下代码行进行了更改。

mutate(stupid_var = rowSums(dplyr :: select(。,'SID74':'NWBIR74'))/ BIR74)

这行代码可能引起了问题。除非我丢失了某些内容,否则似乎没有理由对每一行的整个列进行求和。因此更改了代码以删除rowSums()函数。仍然可以使用mutate函数从每一行数据中的数据执行数学运算,但不涉及任何rowSums()值。

p1 <- nc %>% 
  separate(CNTY_ID,into = c("ID1","ID2"),sep = 2,remove = FALSE) %>% 
               group_by(ID1)  %>% 
               dplyr::summarize(AREA = sum(AREA,na.rm = TRUE),BIR74 = sum(BIR74,SID74 = sum(SID74,NWBIR74 = sum(NWBIR74,na.rm = TRUE)) %>%
               mutate( stupid_var = ( (p2$SID74) + (p2$NWBIR74)) / (p2$BIR74) )
p1

可以从此link.

查看输出 ,

将city_ID分为2个变量可能有一定的原因,但是您没有提供任何提示。在第一个答案中,我进行了拆分,但我忽略了此处使用的拆分变量。

只要数据包含SF几何列,该SF几何就是粘性的,并且会跟随数据。即使数据被子集化。并且,当该sf几何图形存在时,就会导致基本列或行函数(例如sum())出现问题。因此必须在使用sum函数之前删除几何。

在第二个答案中,我使用了与答案1中相同的两个变量。nc数据被分配给第8列和第9列。我的选择是因为没有关于将哪些列加在一起的指导。然后删除sf几何,然后使用rowSums函数为每一行添加每一列的值。

gr_1 <- nc[,c(9:10)]
gr_1 <- st_drop_geometry(gr_1)     
rownames(gr_1) = NULL           # to remove extraneous data from gr_1

xsum <- c(rowSums(gr_1))
head(xsum)                             # displays values of xsum

可以在此link上查看输出: