如何在R中对数据框执行求和和计数操作

4

我有一个包含ID、类型和区域的数据框,我想同时执行两个操作。

ID         Type         Area     
1           Aa          0.02    
2           Ag          0.12    
2           Ag          0.14    
2           Ag          0.80    
2           Bm          0.20    
2           Xm          0.13    

预期结果是

ID          Type       count      area     
1           Aa           1        0.02    
2           Ag           3        1.06 (sum)    
2           Bm           1        0.20    
2           Xm           1        0.13 

我有100-150个ID和类型,每种类型的计数和基面积都不同,但ID相同。在数据框中,如何同时执行求和和计数,并保留类型和ID?

谢谢。


您还没有接受任何答案!难道没有一个对您有帮助吗? - AnilGoyal
4个回答

7

1) 基础R -- aggregate 计数只是一个常量列的总和,因此使用在注释末尾可复现的DF添加这样的一列并使用sum进行聚合。 不使用任何包。

aggregate(cbind(Count, Area) ~ ID + Type, transform(DF, Count = 1), sum)

提供:

  ID Type Count Area
1  1   Aa     1 0.02
2  2   Ag     3 1.06
3  2   Bm     1 0.20
4  2   Xm     1 0.13

2) Base R -- by 使用仅基础R的方法,不依赖于添加一列1的技巧,可以使用 byby调用会生成一个类为by的列表,do.call("rbind", ...)将其转换为数据框。

do.call("rbind", by(DF, DF[1:2], with, 
  data.frame(ID = ID[1], Type = Type[1], Count = length(ID), Area = sum(Area))))

提供:

  ID Type Count Area
1  1   Aa     1 0.02
2  2   Ag     3 1.06
3  2   Bm     1 0.20
4  2   Xm     1 0.13

3) sqldf SQL允许同时分别应用count和sum函数。

library(sqldf)
sqldf("select ID, Type, count(*) as Count, sum(Area) as Area
  from DF
  group by 1, 2")

提供:

  ID Type Count Area
1  1   Aa     1 0.02
2  2   Ag     3 1.06
3  2   Bm     1 0.20
4  2   Xm     1 0.13

4) data.table 数据表 (data.table) 包也可以使用。

library(data.table)

DT <- as.data.table(DF)
DT[, .(Count = .N, Area = sum(Area)), by = "ID,Type"]

提供:

   ID Type Count Area
1:  1   Aa     1 0.02
2:  2   Ag     3 1.06
3:  2   Bm     1 0.20
4:  2   Xm     1 0.13

注意

Lines <- "ID         Type         Area     
1           Aa          0.02    
2           Ag          0.12    
2           Ag          0.14    
2           Ag          0.80    
2           Bm          0.20    
2           Xm          0.13 "

DF <- read.table(text = Lines, header = TRUE)

谢谢,它有效了。聪明的解决方案。只是ID没有按升序显示,例如1,2,3,... 而是按字母顺序排列。 - uday
3
问题没有具体说明ID是否是数字,但在答案的注释中,我们确实将其显示为数字。如果你手上的数据不同,那么需要先将其转换为数字。这说明提供一个可重现的示例在问题中的重要性,就像答案中所做的一样。 - G. Grothendieck

5
我们可以使用dplyr。使用包。
library(dplyr)
df1 %>%
   group_by(ID, Type) %>%
   summarise(count = n(), Area = sum(Area))
# A tibble: 4 x 4
# Groups:   ID [2]
#     ID Type  count  Area
#  <int> <chr> <int> <dbl>
#1     1 Aa        1  0.02
#2     2 Ag        3  1.06
#3     2 Bm        1  0.2 
#4     2 Xm        1  0.13

或者使用来自基本R的by - 注意,base R也包括一些软件包...
by(df1['Area'], df1[1:2], FUN = function(x) cbind(count = nrow(x), Area = sum(x)))

数据

df1 <- structure(list(ID = c(1L, 2L, 2L, 2L, 2L, 2L), Type = c("Aa", 
"Ag", "Ag", "Ag", "Bm", "Xm"), Area = c(0.02, 0.12, 0.14, 0.8, 
0.2, 0.13)), class = "data.frame", row.names = c(NA, -6L))

谢谢,我遇到了一个错误:“Error: n() 应该只在数据上下文中调用。请调用 rlang::last_error() 查看回溯。” - uday

2
< p >在plyr中的另一种可能性:

最初的回答。

library(plyr)
ddply(DF, .(ID,Type), summarize, Count=length(Area), Area=sum(Area))

#   ID Type Count  Area
# 1  1   Aa     1  0.02
# 2  2   Ag     3  1.06
# 3  2   Bm     1  0.20
# 4  2   Xm     1  0.13

2

如果您的数据很大,我建议使用data.table

最初的回答:

library(data.table)
setDT(df)[, .(Area=sum(Area), Count=.N), .(ID, Type)]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接