提问人:MikeTP 提问时间:3/22/2012 最后编辑:JaapMikeTP 更新时间:7/31/2023 访问量:356457
计算每个组内的行数
Count number of rows within each group
问:
我有一个数据帧,我想计算每个组中的行数。我经常使用该函数对数据求和,如下所示: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))
答:
根据 @Joshua 的建议,您可以通过以下方法计算数据帧中的观测值数,其中 = 2007 和 = Nov(假设它们是列):df
Year
Month
nrow(df[,df$YEAR == 2007 & df$Month == "Nov"])
和 ,以下@GregSnow:aggregate
aggregate(x ~ Year + Month, data = df, FUN = length)
使用的简单选项是函数,它将为您提供子集中向量的长度。有时更健壮的是使用 .aggregate
length
function(x) sum( !is.na(x) )
在这种情况下,该函数的替代方法是 ,它还指示 Year 和 Month 的哪些组合与零出现相关联aggregate()
table()
as.data.frame()
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/dplyr 方式:
library(dplyr)
df1 %>% count(Year, Month)
评论
cbind
aggregate(Sepal.Length ~ Species, iris, mean)
aggregate(Sepal.Length ~ Species, iris, length)
df %>% group_by(group, variable) %>% mutate(count = n())
为每行创建一个值为 1 的新变量:Count
df1["Count"] <-1
然后聚合 DataFrame,按列求和: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)
一个没有解决方案的老问题。所以这里是......data.table
用.N
library(data.table)
DT <- data.table(df)
DT[, .N, by = list(year, month)]
评论
.()
list()
setDT()
setDT(df)[, .N, by = .(year, month)]
table
对于我的聚合,我通常最终想要看到平均值和“这个群体有多大”(又名长度)。 所以这是我在这些场合的方便片段;
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)))
例如,问题 df1 中的玩具 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 函数不返回 2014 年 1 月的观测值。aggregate
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答案,如果 R 不包含列,则会抛出错误。但它可以通过以下方式优雅地解决:df1
x
paste
aggregate(paste(Year, Month) ~ Year + Month, data = df1, FUN = NROW)
同样,如果在分组中使用了两个以上的变量,则可以将其概括:
aggregate(paste(Year, Month, Day) ~ Year + Month + Day, data = df1, FUN = NROW)
使用包的 sql 解决方案: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.character:
aggregate(x ~ as.character(Year) + Month, data = df, FUN = length)
在一个或两个变量上。
library(tidyverse)
df_1 %>%
group_by(Year, Month) %>%
summarise(count= n())
在collapse
R
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")]))
两个非常快速的选项是 和 。 是 的快速版本,并使用相同的语法。你可以用它来添加它作为列(-like):collapse
GRPN
fcount
fcount
dplyr::count
add = TRUE
mutate
library(collapse)
fcount(df1, Year, Month) #or df1 %>% fcount(Year, Month)
# Year Month N
# 1 2012 Feb 4
# 2 2014 Jan 3
# 3 2013 Mar 2
# 4 2013 Feb 2
# 5 2012 Jan 2
# 6 2012 Mar 2
# 7 2013 Jan 1
# 8 2014 Feb 3
# 9 2014 Mar 1
GRPN
更接近 的原始语法。首先,使用 对数据进行分组。然后使用 .默认情况下,创建与原始数据匹配的扩展向量。(在 中,它相当于使用 )。用于输出汇总的向量。collapse
GRP
GRPN
GRPN
dplyr
mutate
expand = FALSE
library(collapse)
GRPN(GRP(df1, .c(Year, Month)), expand = FALSE)
具有 100,000 x 3 数据帧和 4997 个不同组的微基准测试。 比任何其他选项都快得多。collapse::fcount
library(collapse)
library(dplyr)
library(data.table)
library(microbenchmark)
set.seed(1)
df <- data.frame(x = gl(1000, 100),
y = rbinom(100000, 4, .5),
z = runif(100000))
dt <- df
mb <-
microbenchmark(
aggregate = aggregate(z ~ x + y, data = df, FUN = length),
count = count(df, x, y),
data.table = setDT(dt)[, .N, by = .(x, y)],
'collapse::fnobs' = df %>% fgroup_by(x, y) %>% fsummarise(number = fnobs(z)),
'collapse::GRPN' = GRPN(GRP(df, .c(x, y)), expand = FALSE),
'collapse::fcount' = fcount(df, x, y)
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# aggregate 159.5459 203.87385 227.787186 223.93050 246.36025 335.0302 100
# count 55.1765 63.83560 74.715889 73.60195 79.20170 196.8888 100
# data.table 8.4483 15.57120 18.308277 18.10790 20.65460 31.2666 100
# collapse::fnobs 3.3325 4.16145 5.695979 5.18225 6.27720 22.7697 100
# collapse::GRPN 3.0254 3.80890 4.844727 4.59445 5.50995 13.6649 100
# collapse::fcount 1.2222 1.57395 3.087526 1.89540 2.47955 22.5756 100
评论
collapse
collapse
timeplyr::fcount()
你也可以从我的包中使用 timeplyr,它接受 dplyr 语法,但在后台使用 collapse。fcount
library(collapse)
library(timeplyr)
library(dplyr)
library(data.table)
library(microbenchmark)
set.seed(1)
df <- data.frame(x = gl(1000, 100),
y = rbinom(100000, 4, .5),
z = runif(100000))
dt <- df
mb <-
microbenchmark(
aggregate = aggregate(z ~ x + y, data = df, FUN = length),
count = count(df, x, y),
data.table = setDT(dt)[, .N, by = .(x, y)],
'collapse::fcount' = collapse::fcount(df, x, y),
'timeplyr::fcount1' = timeplyr::fcount(df, x, y),
'timeplyr::fcount2' = timeplyr::fcount(df, .cols = c("x", "y"), order = FALSE)
)
mb
#> Unit: milliseconds
#> expr min lq mean median uq max
#> aggregate 84.0802 105.10615 123.593910 115.97675 134.65225 255.7676
#> count 40.8108 50.82485 60.718189 56.81630 68.85530 97.4791
#> data.table 3.7106 5.07485 6.273698 5.66645 6.44855 20.0465
#> collapse::fcount 1.0118 1.37400 1.915809 1.61105 2.08465 13.9825
#> timeplyr::fcount1 3.0390 3.74840 5.361852 4.56755 5.83405 44.0072
#> timeplyr::fcount2 1.3787 1.98625 2.640338 2.47025 3.03450 8.6333
#> neval
#> 100
#> 100
#> 100
#> 100
#> 100
#> 100
创建于 2023-11-22 使用 reprex v2.0.2
评论
nrow
, , ...NROW
length
nrow
NROW
length