【问题标题】:Aggregate dataframe in rolling blocks of 3 rows在 3 行的滚动块中聚合数据帧
【发布时间】:2018-10-24 15:53:13
【问题描述】:

我以下面的数据框为例

   df <- data.frame(score=letters[1:15], total1=1:15, total2=16:30)
> df
   score total1 total2
1      a      1     16
2      b      2     17
3      c      3     18
4      d      4     19
5      e      5     20
6      f      6     21
7      g      7     22
8      h      8     23
9      i      9     24
10     j     10     25
11     k     11     26
12     l     12     27
13     m     13     28
14     n     14     29
15     o     15     30

我想aggregate我的数据框通过对具有不同名称的行进行分组来求和,即

  groups  sum1 sum2
 'a-b-c'  6     51
 'c-d-e'  21    60
etc

此类问题的所有给定答案都假定字符串在行中重复。

我用来获取摘要的常用aggregate 函数提供了不同的结果:

aggregate(df$total1, by=list(sum1=df$score %in% c('a','b','c'), sum2=df$score %in% c('d','e','f')), FUN=sum)
   sum1  sum2  x
1 FALSE FALSE 99
2  TRUE FALSE  6
3 FALSE  TRUE 15

【问题讨论】:

  • 另外,大多数人避免使用c 作为变量名,因为它是最常用函数的名称。
  • 我之前评论中的错字。您的第一个示例有重叠组,"a-b-c""c-d-e"c 在这两个组中。您的第二个示例具有非重叠组 "a-b-c""d-e-f"。你要哪个?是只需要每三行,还是要指定字母组合?
  • 您想在一个名称下聚合每 N=3 行吗?像'a-b-c','c-d-e',......或像'a-b-c','d-e-f',......一样不相交?如果 nrows 不是 3 的倍数,如何处理最后的任何粗糙? PS 我将您的数据框名称从令人困惑的c 编辑为明确的df

标签: r aggregation rolling-computation


【解决方案1】:

如果您想要一个 tidyverse 解决方案,这里有一种可能性:

df <- data.frame(score=letters[1:15], total1=1:15, total2=16:30)

df %>%
  mutate(groups = case_when(
    score %in% c("a","b","c") ~ "a-b-c",
    score %in% c("d","e","f") ~ "d-e-f"
  )) %>%
  group_by(groups) %>%
  summarise_if(is.numeric, sum)

返回

# A tibble: 3 x 3
  groups total1 total2
  <chr>   <int>  <int>
1 a-b-c       6     51
2 d-e-f      15     60
3 <NA>       99    234

【讨论】:

    【解决方案2】:

    添加带有类别值的“组”列。

    df$groups = NA
    

    然后像这样定义每个组:

    df$groups[df$score=="a" | df$score=="b" | df$score=="c" ] = "a-b-c"
    

    最终按该列聚合。

    【讨论】:

      【解决方案3】:

      这是适用于任何大小数据框的解决方案。

      df <- data.frame(score=letters[1:15], total1=1:15, total2=16:30)
      
      # I'm adding a row to demonstrate that the grouping pattern works when the 
      # number of rows is not equally divisible by 3.
      df <- rbind(df, data.frame(score = letters[16], total1 = 16, total2 = 31))
      
      # A vector that represents the correct groupings for the data frame.
      groups <- c(rep(1:floor(nrow(df) / 3), each = 3), 
                  rep(floor(nrow(df) / 3) + 1, nrow(df) - length(1:(nrow(df) / 3)) * 3))
      
      # Your method of aggregation by `groups`. I'm going to use `data.table`.
      require(data.table)
      dt <- as.data.table(df)
      dt[, group := groups]
      
      aggDT <- dt[, list(score = paste0(score, collapse = "-"), 
                total1 = sum(total1), total2 = sum(total2)), by = group][
                  , group := NULL]
      aggDT
      
         score total1 total2
      1: a-b-c      6     51
      2: d-e-f     15     60
      3: g-h-i     24     69
      4: j-k-l     33     78
      5: m-n-o     42     87
      6:     p     16     31
      

      【讨论】:

        猜你喜欢
        • 2018-03-04
        • 2015-04-09
        • 2021-12-24
        • 2017-05-12
        • 2015-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-10
        相关资源
        最近更新 更多