具有固定行数的ddply

时间:2012-05-31 16:07:05

标签: r plyr

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

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

3 个答案:

答案 0 :(得分:4)

如果您想使用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)

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

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)

答案 1 :(得分: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表达式变量名称。

答案 2 :(得分:0)

您可以在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)