【问题标题】:Average columns based on other column value and number of rows in R基于 R 中其他列值和行数的平均列
【发布时间】:2016-12-04 23:35:46
【问题描述】:

我正在使用 R 并尝试根据 A 列中的值从另一个数据帧中创建一个平均结果的新数据帧。为了证明我的目标是一些数据:

set.seed(1981)
df <- data.frame(A = sample(c(0,1), replace=TRUE, size=100),
B=round(runif(100), digits=4), 
C=sample(1:1000, 100, replace=TRUE))
head(df, 30)

A   B       C
0   0.6739  459
1   0.5466  178
0   0.154   193
0   0.41    206
1   0.7526  791
1   0.3104  679
1   0.739   434
1   0.421   171
0   0.3653  577
1   0.4035  739
0   0.8796  147
0   0.9138  37
0   0.7257  350
1   0.2125  779
0   0.1502  495
1   0.2972  504
0   0.2406  245
1   0.0325  613
0   0.8642  539
1   0.1096  630
1   0.2113  363
1   0.277   974
0   0.0485  755
1   0.0553  412
0   0.509   24
0   0.2934  795
0   0.0725  413
0   0.8723  606
0   0.3192  591
1   0.5557  177

我需要通过计算 B 列和 C 列的平均值来减小数据的大小,因为 A 列中的值连续保持不变,最多 3 行。如果值 A 保持 1 或 0 超过 3 行,它将滚动到新数据框中的下一行,如下所示。

新的数据框需要以下列:

Value of A  B.Av         C.Av   No. of rows used
0           0.6739       459            1
1           0.5466       178            1
0           0.282        199.5          2
1           0.600666667  634.6666667    3
1           0.421        171            1
0           0.3653       577            1
1           0.4035       739            1
0           0.8397       178            3
1           0.2125       779            1
0           0.1502       495            1
1           0.2972       504            1
0           0.2406       245            1
1           0.0325       613            1
0           0.8642       539            1
1           0.1993       655.6666667    3
0           0.0485       755            1
1           0.0553       412            1
0           0.291633333  410.6666667    3
0           0.59575      598.5          2
1           0.5557       177            1

在搜索 Stack Overflow 时,我还没有找到另一个类似的场景,因此非常感谢任何帮助。

【问题讨论】:

    标签: r average


    【解决方案1】:

    这是一个 base-R 解决方案:

    ## define a function to split the run-length if greater than 3
    split.3 <- function(l,v) {
      o <- c(values=v,lengths=min(l,3)) 
      while(l > 3) {
        l <- l - 3
        o <- rbind(o,c(values=v,lengths=min(l,3)))
      } 
      return(o)
    }
    
    ## compute the run-length encoding of column A
    rl <- rle(df$A)
    
    ## apply split.3 to the run-length encoding
    ## the first column of vl are the values of column A
    ## the second column of vl are the corresponding run-length limited to 3
    vl <- do.call(rbind,mapply(split.3,rl$lengths,rl$values))
    
    ## compute the begin and end row indices of df for each value of A to average
    fin <- cumsum(vl[,2])
    beg <- fin - vl[,2] + 1
    
    ## compute the averages
    out <- do.call(rbind,lapply(1:length(beg), function(i) data.frame(`Value of A`=vl[i,1],
                                                                      B.Av=mean(df$B[beg[i]:fin[i]]),
                                                                      C.Av=mean(df$C[beg[i]:fin[i]]),
                                                                      `No. of rows used`=fin[i]-beg[i]+1)))
    ##   Value.of.A      B.Av     C.Av No..of.rows.used
    ##1           0 0.6739000 459.0000                1
    ##2           1 0.5466000 178.0000                1
    ##3           0 0.2820000 199.5000                2
    ##4           1 0.6006667 634.6667                3
    ##5           1 0.4210000 171.0000                1
    ##6           0 0.3653000 577.0000                1
    ##7           1 0.4035000 739.0000                1
    ##8           0 0.8397000 178.0000                3
    ##9           1 0.2125000 779.0000                1
    ##10          0 0.1502000 495.0000                1
    ##11          1 0.2972000 504.0000                1
    ##12          0 0.2406000 245.0000                1
    ##13          1 0.0325000 613.0000                1
    ##14          0 0.8642000 539.0000                1
    ##15          1 0.1993000 655.6667                3
    ##16          0 0.0485000 755.0000                1
    ##17          1 0.0553000 412.0000                1
    ##18          0 0.2916333 410.6667                3
    ##19          0 0.5957500 598.5000                2
    ##20          1 0.5557000 177.0000                1
    

    【讨论】:

    • 谢谢!我能够根据需要将其应用于我的数据。我以前没有见过“rle”功能,所以感谢您引起我的注意。这对我会有帮助。
    【解决方案2】:

    这是data.table 解决方案:

    library(data.table)
    setDT(df)
    # create two group variables, consecutive A and for each consecutive A every three rows
    (df[,rleid := rleid(A)][, threeWindow := ((1:.N) - 1) %/% 3, rleid]
    
    # calculate the average of the columns grouped by the above two variables
       [, c(.N, lapply(.SD, mean)), .(rleid, threeWindow)]
    
    # drop group variables
       [, `:=`(rleid = NULL, threeWindow = NULL)][])
    
     #   N A         B        C
     #1: 1 0 0.6739000 459.0000
     #2: 1 1 0.5466000 178.0000
     #3: 2 0 0.2820000 199.5000
     #4: 3 1 0.6006667 634.6667
     #5: 1 1 0.4210000 171.0000
     #6: 1 0 0.3653000 577.0000
     #7: 1 1 0.4035000 739.0000
     #8: 3 0 0.8397000 178.0000
     #9: 1 1 0.2125000 779.0000
    #10: 1 0 0.1502000 495.0000
    #11: 1 1 0.2972000 504.0000
    #12: 1 0 0.2406000 245.0000
    #13: 1 1 0.0325000 613.0000
    #14: 1 0 0.8642000 539.0000
    #15: 3 1 0.1993000 655.6667
    #16: 1 0 0.0485000 755.0000
    #17: 1 1 0.0553000 412.0000
    #18: 3 0 0.2916333 410.6667
    #19: 2 0 0.5957500 598.5000
    #20: 1 1 0.5557000 177.0000
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多