计算每个组中的行数

我有一个数据框架,我想计算每个组中的行数。我经常使用 aggregate函数将数据求和如下:

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

现在,我想统计一下观察结果,但似乎找不到适合 FUN的论点。凭直觉,我认为应该是这样的:

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

但是,没有这样的运气。

有什么想法吗?


一些玩具数据:

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))
340174 次浏览

根据@Joshua 的建议,这里有一种方法可以计算 df数据框架中的观测数量,其中 Year = 2007和 Month = Nov (假设它们是列) :

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

以及 aggregate,以下@GregSnow:

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

aggregate一起使用的简单选项是 length函数,它将给出子集中向量的长度。有时使用 function(x) sum( !is.na(x) )会更健壮一些。

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

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")]))

而且没有零发生组合

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

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

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

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

df1["Count"] <-1

然后汇总数据框架,通过 Count列求和:

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

一个没有 data.table解决方案的老问题。

使用 .N

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

对于我的聚合,我通常最终想看到的是均值和“这个群体有多大”(又名长度)。 因此,这是我为这些场合准备的便利片段;

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)

dplyr软件包使用 count/tally命令或 n()函数 完成这项工作:

首先是一些数据:

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

现在开始计数:

library(dplyr)
count(df, year, month)
#piping
df %>% count(year, month)

我们也可以使用稍长一点的版本,包括管道和 n()函数:

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

tally功能:

df %>%
group_by(year, month) %>%
tally()

如果希望在数据中包含缺失的月-年的0计数,可以使用一点 table魔法。

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

例如,问题中的玩具 data.frame df1没有包含对2014年1月的观察。

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月的观测结果。

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:

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

考虑到@Ben 的回答,如果 df1不包含 x列,R 将抛出一个错误。但 paste可以很好地解决这个问题:

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

类似地,如果在分组中使用两个以上的变量,则可以推广:

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

使用 sqldf软件包的 解决方案:

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

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

输出看起来像,

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
>

这里已经有很多精彩的答案,但是我想为那些想要在原始数据集中添加一个新列(包含该行的重复次数)的人再添加一个选项。

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

通过将上述任何一个答案与 merge()函数结合起来,也可以实现同样的功能。

如果您尝试上面的聚合解决方案并得到错误:

变量的无效类型(列表)

因为您使用的是日期或日期时间戳,所以尝试在变量上使用 as.string:

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

在一个或两个变量上。

library(tidyverse)


df_1 %>%
group_by(Year, Month) %>%
summarise(count= n())

R中使用 collapse

library(collapse)
library(magrittr)
df %>%
fgroup_by(year, month) %>%
fsummarise(number = fNobs(x))

我通常使用 桌子函数


df <- data.frame(a=rep(1:8,rep(c(1,2,3, 4),2)),year=2011:2021,month=c(1,3:10))


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