计算每个组中的行数


121

我有一个数据框,我想计算每个组中的行数。我通常使用该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))

17
nrowNROWlength...
约书亚乌尔里希

15
我一直在读这个问题,是在寻求一种有趣的方法来计算事物(我想这与许多无趣的方法相对)。
Hong Ooi 2012年

6
@JoshuaUlrich:nrow没有为我工作,但NROWlength正常工作。+1
Prolix

Answers:


69

当前的最佳做法(tidyverse)是:

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

是否有一种方法可以聚合变量并进行计数(如聚合中的两个函数:均值+计数)?我需要得到一个列的平均值,行中其他列的值相同数量
SOP

1
我最好cbind的结果aggregate(Sepal.Length ~ Species, iris, mean)aggregate(Sepal.Length ~ Species, iris, length)
geotheory

我已经做到了,但是除了聚合的那一列,我似乎每列得到2倍。所以我做了他们的合并,它似乎是确定
SOP

6
我不知道,但这也可能有用...df %>% group_by(group, variable) %>% mutate(count = n())
Manoj Kumar

1
是的,dplyr现在是最佳实践。
geotheory,2013年

67

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

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

并在aggregate@GregSnow之后:

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

47

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()

37

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

使用 .N

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

1
现在使用的标准,.()而不是使用data.frame list()并将setDT()其转换为data.table。所以一步setDT(df)[, .N, by = .(year, month)]
sindri_baldur

23

aggregatelength函数一起使用的简单选项是函数,该函数将为您提供子集中向量的长度。有时要使用更强大的功能function(x) sum( !is.na(x) )


18

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

df1["Count"] <-1

然后聚合数据框,按Count列求和:

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

只是要注意的是,如果你使用的是默认的,对于非公式法aggregate,没有必要每个变量的命名by=一样list(year=df1$year)等。data.frame是一个list已经如此aggregate(df1[c("Count")], by=df1[c("Year", "Month")], FUN=sum, na.rm=TRUE)会工作。
thelatemail

17

aggregate()在这种情况下,该函数的替代方法是table()with 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),]

7

如果要在数据中包括月份数的0计数,可以使用一些table魔术。

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

例如,问题df1中的toy data.frame不包含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

5

对于我的汇总,我通常最终希望看到平均值和“该组的大小”(又名长度)。因此,这是我在这些情况下的方便摘录;

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)

4

一个 解决方案使用sqldf包:

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

1

考虑到@Ben答案,如果R 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)

0

您可以使用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
> 

0

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

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

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


0

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

变量的无效类型(列表)

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

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

在一个或两个变量上。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.