【问题标题】:Count number of rows within each group计算每组中的行数
【发布时间】:2012-04-06 05:45:54
【问题描述】:

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

【问题讨论】:

  • nrow, NROW, length...
  • 我一直在阅读这个问题,希望找到一种有趣的方式来计算事物(我猜与许多不有趣的方式相反)。
  • @JoshuaUlrich:nrow 对我不起作用,但 NROWlength 工作正常。 +1

标签: r dataframe aggregate r-faq


【解决方案1】:

按照@Joshua 的建议,您可以通过以下方式计算df 数据框中的观察次数,其中Year = 2007 和Month = Nov(假设它们是列):

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

aggregate,跟随@GregSnow:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      在这种情况下,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),]
      

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

        • 有没有办法聚合变量并进行计数(如聚合中的 2 个函数:均值 + 计数)?我需要获取一列的平均值和其他列中相同值的行数
        • 我会 cbind aggregate(Sepal.Length ~ Species, iris, mean)aggregate(Sepal.Length ~ Species, iris, length) 的结果
        • 我不知道,但这也可能有用...df %&gt;% group_by(group, variable) %&gt;% mutate(count = n())
        • 是的,dplyr 现在是最佳实践。
        • 我是 dplyr 的日常用户,但仍然不一定将其称为最佳实践,更像是常见的个人偏好
        【解决方案5】:

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

        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) 可以工作。
        【解决方案6】:

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

        使用.N

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

        【讨论】:

        • 现在的标准是使用.() 而不是list()setDT() 将data.frame 转换为data.table。所以一步到位setDT(df)[, .N, by = .(year, month)].
        【解决方案7】:

        对于我的聚合,我通常最终希望看到平均值和“这个组有多大”(又名长度)。 所以这是我在这些场合下得心应手的 sn-p;

        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)
        

        【讨论】:

          【解决方案8】:

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

          【讨论】:

            【解决方案9】:

            如果您想在数据中包含 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
            

            【讨论】:

              【解决方案10】:

              考虑到@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)
              

              【讨论】:

                【解决方案11】:

                使用sqldf 包的 解决方案:

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

                【讨论】:

                  【解决方案12】:

                  您可以将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
                  > 
                  

                  【讨论】:

                    【解决方案13】:

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

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

                    同样可以通过将上述任何答案与merge() 函数结合起来来实现。

                    【讨论】:

                      【解决方案14】:

                      如果您尝试上述聚合解决方案并收到错误消息:

                      变量的类型(列表)无效

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

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

                      在一个或两个变量上。

                      【讨论】:

                        【解决方案15】:
                        library(tidyverse)
                        
                        df_1 %>%
                          group_by(Year, Month) %>%
                          summarise(count= n()) 
                        

                        【讨论】:

                          【解决方案16】:

                          R 中使用collapse

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

                          【讨论】:

                            【解决方案17】:

                            我通常使用table函数

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

                            【讨论】:

                              猜你喜欢
                              • 2019-08-22
                              • 2021-12-22
                              • 1970-01-01
                              • 1970-01-01
                              • 2020-02-12
                              • 2021-07-17
                              相关资源
                              最近更新 更多