【问题标题】:Summarizing multiple columns by two variables通过两个变量汇总多列
【发布时间】:2015-11-13 17:50:10
【问题描述】:

这是我第一次使用 R,如果这个问题措辞不当,请原谅我。我有一个导入到 R 中的 .csv 文件,我正在尝试总结一些数据。每一行数据,如果对于给定的年份、研究地点和区域,并且每一列都有存在的物种数量。每个物种有 4 列,因为有 4 次调查可以看到该物种。

我正在尝试按年份和研究地点获取每个物种的总和。列 5:8 是一个物种,9:12 是另一个,13:16 是另一个,依此类推。这是我认为可以按年份 (YYYY) 和研究区域 (SAR) 总结 5:8 列的代码:

aggregate(test[,5:8],by = list("SAR","YYYY"), FUN = sum, na.rm = TRUE)

这给了我“参数必须具有相同长度”的错误消息。谁能帮我完成这个初始步骤?

以下是部分数据:

SAR    YYYY GRID_ID WID     col1 col2 col3 col4
BCPALP  2005    1   1189    NA  NA  0   0
BCPALP  2005    1   1190    0   NA  0   0
BCPALP  2005    1   1191    0   0   NA  NA
BCPALP  2005    1   1192    0   NA  NA  NA
BCPALP  2005    1   1194    NA  NA  1   NA
BCPALP  2005    1   1195    NA  NA  1   NA
BCPALP  2005    1   1196    0   NA  0   NA
BCPALP  2005    1   1198    0   NA  0   NA
BCPALP  2005    1   1199    0   NA  0   0

我希望得到这样的输出:

SAR    YYYY    total of columns 1:4
BCPALP 2005    2

这是我刚刚尝试的代码。

aggregate(cbind("col1", "col2", "col3", "col4")~SAR+YYYY, test, FUN=sum, na.rm=TRUE, na.action=NULL)

它给了我一条错误消息,指出“可变长度不同(为 'SAR' 找到)”。

我回去查了一下数据,所有的变长都是一样的。

【问题讨论】:

  • 请展示一些示例数据和预期输出。
  • 这是我掌握的一些数据:
  • 请在您的帖子中更新
  • 顺便说一句,你能指定YYYYSARs在数据集中的位置吗
  • 抱歉,我无法弄清楚如何将数据表的一部分添加到评论中。 SAR 和 YYYY 分别是第 1 列和第 2 列的标题。

标签: r


【解决方案1】:

我们可以使用aggregatedata.tabledplyr。如果我们使用aggregate的公式方法,当不同列中有NA值时,我们需要设置na.action=NULL。默认情况下,na.action=na.omit,因此如果其中一列中有单个 NA,则将从计算中删除该行。

aggregate(cbind(col1, col2, col3, col4)~SAR+YYYY, test,
                        FUN=sum, na.rm=TRUE, na.action=NULL)
#   SAR YYYY col1 col2 col3 col4
#1 BCPALP 2005    0    0    2    0

使用dplyr,我们按“SAR”、“YYYY”分组,并使用summarise_each获取每个“col”的sum

library(dplyr)
test %>%
     group_by(SAR, YYYY) %>%
     summarise_each(funs(sum=sum(., na.rm=TRUE)), 5:ncol(test))
#     SAR  YYYY  col1  col2  col3  col4
#   (chr) (int) (int) (int) (int) (int)
#1 BCPALP  2005     0     0     2     0

或者data.table。我们将“data.frame”转换为“data.table”(setDT(test)),按“SAR”、“YYYY”分组,循环遍历 Data.table 的子集(.SD)并得到sum .要循环的列在.SDcols 中指定。

library(data.table)
setDT(test)[, lapply(.SD, sum, na.rm=TRUE), by = .(SAR, YYYY),
             .SDcols= 5:ncol(test)]  
#      SAR YYYY col1 col2 col3 col4
#1: BCPALP 2005    0    0    2    0

更新

假设在聚合之后,我们需要获取列 'col1:col4'、'col5:col8' 等的逐行总和。

 DT <- setDT(test1)[, lapply(.SD, sum, na.rm=TRUE),
              by = .(SAR, YYYY), .SDcols= 5:ncol(test1)]
 DT1 <- melt(DT, id.var=c('SAR', 'YYYY'))[, i1 := as.numeric(gl(.N, 4, .N)),
            .(SAR, YYYY)]
 dcast(DT1, SAR+YYYY~i1, value.var='value', sum)

数据

 test <- structure(list(SAR = c("BCPALP", "BCPALP",
"BCPALP", "BCPALP", 
"BCPALP", "BCPALP", "BCPALP", "BCPALP", "BCPALP"), YYYY = c(2005L, 
2005L, 2005L, 2005L, 2005L, 2005L, 2005L, 2005L, 2005L),
GRID_ID = c(1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), WID = c(1189L, 1190L, 1191L, 
1192L, 1194L, 1195L, 1196L, 1198L, 1199L), col1 = c(NA, 0L, 0L, 
0L, NA, NA, 0L, 0L, 0L), col2 = c(NA, NA, 0L, NA, NA, NA, NA, 
NA, NA), col3 = c(0L, 0L, NA, NA, 1L, 1L, 0L, 0L, 0L), col4 = c(0L, 
0L, NA, NA, NA, NA, NA, NA, 0L)), .Names = c("SAR", "YYYY",
"GRID_ID", 
"WID", "col1", "col2", "col3", "col4"), class = "data.frame", 
 row.names = c(NA, -9L))

set.seed(24)
m1 <- matrix(sample(c(NA,0:5), 9*4, replace=TRUE),ncol=4, 
           dimnames=list(NULL, paste0('col', 5:8)))
test1 <- cbind(test, m1) 

【讨论】:

  • 另外,我如何告诉 R 汇总 5:8、9:12、13:16 等列,直到我的数据结束?
  • @HVS 正如我所展示的,您可以在dplyrdata.table 中使用dplyr.SDcols 指定select 中的列位置。即.SDcols= 5:ncol(test).
  • 当我将您在上面发布的数据复制并粘贴到 R 中时,它会运行,然后我没有收到聚合函数的错误消息,该错误消息一定是由于创建列的方式在 excel 中,然后转换为 .csv 文件。我对 .SDcols= 5:ncol(test) 命令仍然有点不清楚。我不明白该语句如何告诉 R 阅读我上面提到的列。
  • @HVS 实际上,您通过引用"col1" 等得到aggregate 的错误。我们在.SDcols 中指定列的位置或名称,并基于此,我们循环那些列 (lapply(.SD, ...)
  • 我总共有 328 列。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-11
  • 1970-01-01
  • 1970-01-01
  • 2016-04-08
  • 2013-07-16
  • 2018-03-27
  • 2023-01-12
相关资源
最近更新 更多