【问题标题】:ddply with fixed number of rows具有固定行数的 ddply
【发布时间】:2012-05-31 16:07:05
【问题描述】:

我想按“行数”分解我的数据。也就是说,我想向我的函数发送固定数量的行,当我到达数据帧的末尾(最后一个块)时,我只需要发送块,无论它是否具有固定的行数或更少。像这样的:

ddply(df, .(8 rows), .fun=somefunction)

【问题讨论】:

    标签: r plyr


    【解决方案1】:

    如果你想使用plyr你可以添加一个分类栏:

    df <- data.frame(x=rnorm(100), y=rnorm(100))
    
    somefunction <- function(df) {
        data.frame(mean(df$x), mean(df$y))
    }
    
    df$category <- rep(letters[1:10], each=10)
    
    ddply(df, .(category), somefunction)
    

    但是,在这种情况下,apply 系列可能是更好的选择:

    somefunction <- function(n, x, y) {
        data.frame(mean(x[n:(n+9)]), mean(y[n:n+9]))
    }
    
    lapply(seq(1, nrow(df), by=10), somefunction, x=df$x, y=df$y)
    

    【讨论】:

      【解决方案2】:

      如果对速度和简洁感兴趣,那么为了完整性(并使用 4 而不是 8 的块大小来保持示例简短):

      require(data.table)
      set.seed(0)
      DT = data.table(a=rnorm(10))
      DT
                       a
       [1,]  1.262954285
       [2,] -0.326233361
       [3,]  1.329799263
       [4,]  1.272429321
       [5,]  0.414641434
       [6,] -1.539950042
       [7,] -0.928567035
       [8,] -0.294720447
       [9,] -0.005767173
      [10,]  2.404653389
      
      DT[,list(sum=sum(a),groupsize=.N),by=list(chunk=(0:(nrow(DT)-1))%/%4)]
           chunk       sum groupsize
      [1,]     0  3.538950         4
      [2,]     1 -2.348596         4
      [3,]     2  2.398886         2
      

      诚然,这是一个相当长的声明。它命名列并返回组大小,以显示最后一个块确实只包含所需的 2 行。

      一旦感到舒服,它就在做正确的事,它可以缩短为:

      DT[,sum(a),by=list(chunk=(0:(nrow(DT)-1))%/%4)]
           chunk        V1
      [1,]     0  3.538950
      [2,]     1 -2.348596
      [3,]     2  2.398886
      

      请注意,您可以像这样即时进行聚合;它们不需要先添加到数据中。如果您在生产脚本中有很多不同的聚合,或者只是想与命令行中的数据进行交互,那么像这样非常小的生产力差异有时会有所帮助,具体取决于您的工作流程。

      注意:我选择了 sum,但可以将其替换为 somefunction(.SD) 或(更有可能)只是 list(exp1,exp2,...),其中每个 exp 是任何将列名视为变量名的 R 表达式。

      【讨论】:

      • +1 总有一天我也会拥抱data.table... 的力量
      【解决方案3】:

      您可以在对 ddply 的调用中定义 8 行 ID。

      不是特别优雅,但使用ddply(和head作为示例函数)

      df <- data.frame(x = rnorm(100), y = rnorm(100))
      ddply(df, .(row_id = rep(seq(ceiling(nrow(df) / 8)), each = 8)[1:nrow(df)]),
                   head, n = 1)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-17
        相关资源
        最近更新 更多