【问题标题】:mean of n rows by grouping another column in r通过对 r 中的另一列进行分组来平均 n 行
【发布时间】:2017-08-12 02:57:37
【问题描述】:

我有一个数据框,我需要为每 n 行计算 x 的平均值
通过分组名称,假设 n= 3
样本数据集df:

 Name     X  
  A      3.1     
  A      2.5    
  A      3.6  
  A      3.4  
  B      4.6  
  B      1.8  
  B      3.4 

对于每个名称,前 3 行的平均值,然后是下 3 行的平均值,
如果最后

到目前为止,我已经能够分别对 3 行或名称进行分组。
任何有关如何暗示这两者在一起的帮助将不胜感激。

## by grouping 3 rows##
final1<-aggregate(df$X,list(rep(1(nrow(df)%/%n+1),each=n,len=nrow(df))),mean)[-1]  

##by grouping name##
final2<- df %>% group_by(Name) %>% summarise(value=mean(df$X))  

期望的输出是:

  Name      X     
   A      3.066  
   A      3.400  
   B      3.266  

感谢您的帮助!

【问题讨论】:

  • 您可以尝试在df %&gt;% group_by(Name) %&gt;% mutate(idx = ceiling(seq_len(n())/3)) %&gt;% group_by(idx, add=T) %&gt;% summarise(value=mean(X)) 的脉络中添加一个辅助分组变量。
  • 我已经尝试按 2 个变量进行分组,但没有奏效。感谢您的帮助

标签: r group-by aggregate mean


【解决方案1】:

我们可以使用row_number函数,同时也可以使用group_by提出解决方案:

我们首先创建一个名为row_num_mod 的变量,它采用row_number mod 3。然后我们可以按row_num_modName 进行分组,以找出观察属于哪个实例。

我们可以再次使用row_number,这样我们实际上是在订购不同的值 mod 3。

dat %>%
    group_by(Name) %>%
    mutate(row_num_mod = row_number() %% 3) %>% 
    ungroup() %>%
    group_by(row_num_mod, Name) %>%
    mutate(row_num2 = row_number()) %>% # which instance of x mod 3 is this?
    ungroup() %>%
    group_by(Name, row_num2) %>%
    summarise(Mean = mean(X))

   Name row_num2     Mean
  <chr>    <int>    <dbl>
1     A        1 3.066667
2     A        2 3.400000
3     B        1 3.266667

清晰度

为了演示我们添加的字段,下面是添加row_num2后的数据样子:

   Name     X row_num_mod row_num2
  <chr> <dbl>       <dbl>    <int>
1     A   3.1           1        1
2     A   2.5           2        1
3     A   3.6           0        1
4     A   3.4           1        2
5     B   4.6           1        1
6     B   1.8           2        1
7     B   3.4           0        1

数据

dat <- read.table(text = " Name     X  
  A      3.1     
  A      2.5    
  A      3.6  
  A      3.4  
  B      4.6  
  B      1.8  
  B      3.4 ", header = TRUE, stringsAsFactors = FALSE)

【讨论】:

  • 我认为这可以缩短为dat %&gt;% group_by(Name) %&gt;% mutate(ind = cumsum(row_number() %% 3 == 1)) %&gt;% group_by(ind, add = TRUE) %&gt;% summarise(Mean = mean(X))`
  • 太棒了!这正是我一直在寻找的。没有意识到 mutate() 可以用于此!
【解决方案2】:

另一种方法是使用%/%n() 而不是%%row_number

dat %>% 
  group_by(Name) %>% 
  mutate(ind = 0:(n() - 1) %/% 3) %>% 
  group_by(ind, add = TRUE) %>% 
  summarise(Mean = mean(X))
## Source: local data frame [3 x 3]
## Groups: Name [?]
## 
##    Name   ind     Mean
##   <chr> <dbl>    <dbl>
## 1     A     0 3.066667
## 2     A     1 3.400000
## 3     B     0 3.266667

【讨论】:

    【解决方案3】:

    使用 zoo 包中的 rollapply。我们可以使用 by = 3 参数以 3 的步长移动滚动窗口,我们可以使用 partial = TRUE 包含小于 3 的组,这些组留在最后。我在这里演示了使用 data.table 进行分组,尽管您同样可以使用 dplyr 或基本函数进行分组:

    dt[, rollapply(X, 3, mean, by = 3, align = "left", partial=T), by=Name]
    #    Name       V1
    # 1:    A 3.066667
    # 2:    A 3.400000
    # 3:    B 3.266667
    

    数据和库:

    library(data.table)
    library(zoo)
    dt= fread ("Name     X  
    A      3.1     
    A      2.5    
    A      3.6  
    A      3.4  
    B      4.6  
    B      1.8  
    B      3.4 ")
    

    【讨论】:

      【解决方案4】:

      这是data.table的另一个解决方案:

      library("data.table")
      dt <- fread(
      ' Name     X  
        A      3.1     
        A      2.5    
        A      3.6  
        A      3.4  
        B      4.6  
        B      1.8  
        B      3.4 ')
      dt[, n3:=gl(.N, 3, length=.N), by=Name]
      dt[, .(X=mean(X)), by=.(Name, n3)]
      # > dt[, .(X=mean(X)), by=.(Name, n3)]
      #    Name n3        X
      # 1:    A  1 3.066667
      # 2:    A  2 3.400000
      # 3:    B  1 3.266667
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-24
        • 2016-06-05
        • 2017-08-20
        相关资源
        最近更新 更多