关于r:计算每个组中的行数

Count number of rows within each group

我有一个数据框,我想计算每个组中的行数。 我通常使用aggregate函数对数据求和,如下所示:

1
df2 <- aggregate(x ~ Year + Month, data = df1, sum)

现在,我想对观察值进行计数,但似乎找不到FUN的正确参数。 凭直觉,我认为应该是这样的:

1
df2 <- aggregate(x ~ Year + Month, data = df1, count)

但是,没有这种运气。

有任何想法吗?

一些玩具数据:

1
2
3
4
set.seed(2)
df1 <- data.frame(x = 1:20,
                  Year = sample(2012:2014, 20, replace = TRUE),
                  Month = sample(month.abb[1:3], 20, replace = TRUE))


按照@Joshua的建议,这是一种您可以在df数据框中计算观察值数量的方法,其中Year = 2007,Month = Nov(假设它们是列):

1
nrow(df[,df$YEAR == 2007 & df$Month =="Nov"])

并使用aggregate,紧跟@GregSnow:

1
aggregate(x ~ Year + Month, data = df, FUN = length)

当前的最佳实践(tidyverse)是:

1
2
require(dplyr)
df1 %>% count(Year, Month)


dplyr软件包使用Count / tally命令或n()函数执行此操作:

首先,一些数据:

1
df <- data.frame(x = rep(1:6, rep(c(1, 2, 3), 2)), year = 1993:2004, month = c(1, 1:11))

现在计数:

1
2
3
4
library(dplyr)
count(df, year, month)
#piping
df %>% count(year, month)

我们还可以使用带有管道和n()函数的稍长版本:

1
2
3
df %>%
  group_by(year, month) %>%
  summarise(number = n())

tally函数:

1
2
3
df %>%
  group_by(year, month) %>%
  tally()

没有data.table解决方案的老问题。所以这里...

使用.N

1
2
3
library(data.table)
DT <- data.table(df)
DT[, .N, by = list(year, month)]


aggregate一起使用的简单选项是length函数,该函数将为您提供子集中向量的长度。有时,更健壮的是使用function(x) sum( !is.na(x) )


为每行创建一个值为1的新变量Count

1
df1["Count"] <-1

然后聚合数据帧,并通过Count列求和:

1
df2 <- aggregate(df1[c("Count")], by=list(Year=df1$Year, Month=df1$Month), FUN=sum, na.rm=TRUE)


在这种情况下,aggregate()函数的替代项是table()as.data.frame(),这还将指示Year和Month的哪些组合与零出现相关联

1
2
3
df<-data.frame(x=rep(1:6,rep(c(1,2,3),2)),year=1993:2004,month=c(1,1:11))

myAns<-as.data.frame(table(df[,c("year","month")]))

而且没有零发生的组合

1
myAns[which(myAns$Freq>0),]

如果要为数据中缺少的月份年份包括0个计数,则可以使用table魔术。

1
data.frame(with(df1, table(Year, Month)))

例如,问题df1中的toy data.frame不包含2014年1月的观测值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
df1
    x Year Month
1   1 2012   Feb
2   2 2014   Feb
3   3 2013   Mar
4   4 2012   Jan
5   5 2014   Feb
6   6 2014   Feb
7   7 2012   Jan
8   8 2014   Feb
9   9 2013   Mar
10 10 2013   Jan
11 11 2013   Jan
12 12 2012   Jan
13 13 2014   Mar
14 14 2012   Mar
15 15 2013   Feb
16 16 2014   Feb
17 17 2014   Mar
18 18 2012   Jan
19 19 2013   Mar
20 20 2012   Jan

基本的R aggregate函数不会返回2014年1月的观测值。

1
2
3
4
5
6
7
8
9
10
aggregate(x ~ Year + Month, data = df1, FUN = length)
  Year Month x
1 2012   Feb 1
2 2013   Feb 1
3 2014   Feb 5
4 2012   Jan 5
5 2013   Jan 2
6 2012   Mar 1
7 2013   Mar 3
8 2014   Mar 2

如果您希望用0作为计数来观察这个月年,那么上面的代码将返回一个data.frame,其中包含所有月年组合的计数:

1
2
3
4
5
6
7
8
9
10
11
data.frame(with(df1, table(Year, Month)))
  Year Month Freq
1 2012   Feb    1
2 2013   Feb    1
3 2014   Feb    5
4 2012   Jan    5
5 2013   Jan    2
6 2014   Jan    0
7 2012   Mar    1
8 2013   Mar    3
9 2014   Mar    2

使用sqldf包的sql解决方案:

1
2
3
4
library(sqldf)
sqldf("SELECT Year, Month, COUNT(*) as Freq
       FROM df1
       GROUP BY Year, Month")

对于我的汇总,我通常最终希望看到平均值和"这个组有多大"(又称长度)。
因此,这是我在这些场合下的方便摘录;

1
2
3
4
agg.mean <- aggregate(columnToMean ~ columnToAggregateOn1*columnToAggregateOn2, yourDataFrame, FUN="mean")
agg.count <- aggregate(columnToMean ~ columnToAggregateOn1*columnToAggregateOn2, yourDataFrame, FUN="length")
aggcount <- agg.count$columnToMean
agg <- cbind(aggcount, agg.mean)

考虑到@Ben答案,如果df1不包含x列,R将引发错误。但是可以使用paste优雅地解决它:

1
aggregate(paste(Year, Month) ~ Year + Month, data = df1, FUN = NROW)

同样,如果在分组中使用了两个以上的变量,则可以将其推广:

1
aggregate(paste(Year, Month, Day) ~ Year + Month + Day, data = df1, FUN = NROW)


如果您尝试上述汇总解决方案,但出现错误:

变量的无效类型(列表)

由于您使用的是日期或日期时间戳记,因此请尝试在变量上使用as.character:

1
aggregate(x ~ as.character(Year) + Month, data = df, FUN = length)

在一个或两个变量上。


这里已经有很多奇妙的答案,但是对于那些想要向原始数据集添加新列(包含重复行的次数)的人,我想再添加一个选项。

1
2
df1$counts <- sapply(X = paste(df1$Year, df1$Month),
                     FUN = function(x) { sum(paste(df1$Year, df1$Month) == x) })

通过将上述任何答案与merge()函数组合在一起,可以实现相同的目的。


您可以将by函数用作by(df1$Year, df1$Month, count),这将生成所需聚合的列表。

输出看起来像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
df1$Month: Feb
     x freq
1 2012    1
2 2013    1
3 2014    5
---------------------------------------------------------------
df1$Month: Jan
     x freq
1 2012    5
2 2013    2
---------------------------------------------------------------
df1$Month: Mar
     x freq
1 2012    1
2 2013    3
3 2014    2
>