使用dplyr按组计算行数

135

我正在使用mtcars数据集。 我想找到特定数据组合的记录数。 类似于SQL中count(*) group by子句的内容。 plyr中的ddply()对我有用。

library(plyr)
ddply(mtcars, .(cyl,gear),nrow)

有输出

  cyl gear V1
1   4    3  1
2   4    4  8
3   4    5  2
4   6    3  2
5   6    4  4
6   6    5  1
7   8    3 12
8   8    5  2

使用此代码

library(dplyr)
g <- group_by(mtcars, cyl, gear)
summarise(g, length(gear))

有输出

  length(cyl)
1          32

我发现各种可以用作传递给summarise()的函数,但没有一个对我有效。我找到了一个函数sum(G),它返回

I found various functions to pass in to summarise() but none seem to work for me. One function I found is sum(G), which returned

Error in eval(expr, envir, enclos) : object 'G' not found

尝试使用n(),返回了

Error in n() : This function should not be called directly

我做错了什么?我该如何让group_by() / summarise()对我起作用?


我无法复现这个问题。我的输出结果与 “ddply” 的一样。您使用的 dplyr 版本是多少?尝试更新一下吧。 - joran
1
你使用的R版本是多少?这可能导致了行为上的差异。我也在使用Ubuntu电脑时尝试过了,结果仍然一样。 - charmee
我使用的是3.0.2版本,但我觉得这不会有什么影响,除非你使用的R版本非常旧。 - joran
你所声称得到的结果只有在 g 实际上没有被分组时才有意义。因此,我会寻找你可能以某种方式取消分组数据框的原因。 - joran
2
谢谢!问题解决了。如果我同时加载了plyr和dplyr包,summarise函数的效果就不如预期。只要重新启动会话(而且默认不加载所有常规包),我就能让它正常工作了。呼~ - charmee
显示剩余8条评论
6个回答

188

dplyr 中有一个特殊的函数 n(),可以用于计算行数(可能是在分组内):

library(dplyr)
mtcars %>% 
  group_by(cyl, gear) %>% 
  summarise(n = n())
#Source: local data frame [8 x 3]
#Groups: cyl [?]
#
#    cyl  gear     n
#  (dbl) (dbl) (int)
#1     4     3     1
#2     4     4     8
#3     4     5     2
#4     6     3     2
#5     6     4     4
#6     6     5     1
#7     8     3    12
#8     8     5     2

不过,dplyr 还提供了一个方便的count函数,可以用更少的打字来完成同样的操作:

count(mtcars, cyl, gear)          # or mtcars %>% count(cyl, gear)
#Source: local data frame [8 x 3]
#Groups: cyl [?]
#
#    cyl  gear     n
#  (dbl) (dbl) (int)
#1     4     3     1
#2     4     4     8
#3     4     5     2
#4     6     3     2
#5     6     4     4
#6     6     5     1
#7     8     3    12
#8     8     5     2

23

我认为您正在寻找的内容如下。

cars_by_cylinders_gears <- mtcars %>%
  group_by(cyl, gear) %>%
  summarise(count = n())

这是使用dplyr包。这本质上是docendo discimus提供的count()解决方案的长手版本。


对我来说可以运行。关键部分是不指定用于按组的列名周围的引号。 - ivan866

21
另一种方法是使用双冒号,这将有助于避免与其他包中具有类似名称的函数可能发生的冲突。
mtcars %>% 
  dplyr::group_by(cyl, gear) %>%
  dplyr::summarise(length(gear))

编辑后添加为什么使用冒号会很有用,尽管我认为这个答案的主要观点是使用“length”。 - NelsonGon

3

另一个选项,不一定更优雅,但不需要引用特定的列:

mtcars %>% 
  group_by(cyl, gear) %>%
  do(data.frame(nrow=nrow(.)))

这相当于使用count()函数:
library(dplyr, warn.conflicts = FALSE)
all.equal(mtcars %>% 
            group_by(cyl, gear) %>%
            do(data.frame(n=nrow(.))) %>% 
            ungroup(),
          count(mtcars, cyl, gear), check.attributes=FALSE)
#> [1] TRUE

不确定您的意思,它会给出每个组的nrow,就像count一样? - Matifou
我不确定,因为这是6年前的事了。可能有些函数已经改变了。我已经删除了我的旧评论。 - Hack-R
1
感谢 @Hack-R! - Matifou

1

另一个选项是使用dplyr的函数tally。以下是一个可重现的示例:

library(dplyr)
mtcars %>% 
  group_by(cyl, gear) %>% 
  tally()
#> # A tibble: 8 × 3
#> # Groups:   cyl [3]
#>     cyl  gear     n
#>   <dbl> <dbl> <int>
#> 1     4     3     1
#> 2     4     4     8
#> 3     4     5     2
#> 4     6     3     2
#> 5     6     4     4
#> 6     6     5     1
#> 7     8     3    12
#> 8     8     5     2

本文创建于2022年9月11日,使用reprex v2.0.2


1
可以简单地使用 dplyr 来完成这个任务:
library(dplyr)

# Use the function add_count() and name the new variable as "count"

mtcars %>%
  add_count(cyl, gear, name = "count")

这样做的好处是,当你提到变量时,你不需要将列分组,因为add_count()函数会为你做这个。此外,这还允许你保留数据框中的其他变量(如果有的话)。

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