是否可以使用transform在data.frame上按行添加操作结果?

时间:2012-03-08 10:18:07

标签: r dataframe plyr

我有点困惑。我经常使用像这样的变换

    ddply(data.frame, 1, transform, new.column = function(old.col.1,old.col.2,...))

这也是recommended by Hadley

但最近I asked a question和哈德利说过:

  

不要使用变换。它是一个适合交互使用的辅助函数,而不是用于编程。

转换错了吗?我想我现在确信这是愚蠢的:

   transform(data.frame,col2=fun(col1)).

但它在ddply设置中不是很有用吗?

1 个答案:

答案 0 :(得分:1)

transform中使用ddply和将函数transform()作为独立使用之间存在差异。这样做会好得多(也更快):

Mydata$col3 <- fun(Mydata$col1, Mydata$col2)

如果要更改多个列,函数组合ddply / transform特别有用,例如

Mynewdata <- ddply(Mydata,1,transform,col3=fun1(col1,col2), col4=fun2(col1,col2))

即便如此,您还可以使用within()更灵活的选项,允许您使用计算结果来计算下一行:

Mynewdata <- within(Mydata,{
    col2 <- fun1(col1)
    col3 <- fun2(col1,col2)
})

transform()的东西是它特别编写为交互使用。如果在函数中使用它,可能会遇到麻烦。它以这种方式类似于subset():它们是便利功能,但它们在更复杂的代码中使用既不快也不安全。

ddply()的意见不同。在某些情况下,它可以快速工作,并提供非常干净和可读的代码,在其他情况下,我认为它严重矫枉过正。当您必须使用非向量化函数时,ddply()通常可以更快更轻松地工作,在这种情况下,上述选项将无效。但为此,您还可以选择使用mapply:

Mynewdata <- within(Mydata, col3 <- mapply(myfun,col1,col2))
在这种情况下,mapply也可以更快。给你一个基本的例子:

Mydata <- data.frame(col1=rnorm(5),col2=rpois(5,3))
myfun <- function(x,y){
    if(y == 0) mean(x) else
     mean(c(x,seq(1,y,by=1)))
}

code1 <- expression(Newdata <- ddply(Mydata,1,transform,col3=myfun(col1,col2)))
code2 <- expression(Newdata2 <- within(Mydata, col3 <- mapply(myfun,col1,col2)))

> benchmark(code1,code2)
   test replications elapsed relative 
1 code1          100    0.50     12.5 
2 code2          100    0.04      1.0 

我对ddply()的主要问题是,无法保证观察的顺序,如下面的示例输出中所示:

Mydata              Newdata2                    Newdata
        col1 col2         col1 col2      col3         col1 col2      col3
1 0.07060223    4 | 0.07060223    4 2.0141204 | 0.05658259    2 1.0188609
2 1.84645791    2 | 1.84645791    2 1.6154860 | 0.07060223    4 2.0141204
3 0.05658259    2 | 0.05658259    2 1.0188609 | 0.84119845    1 0.9205992
4 0.89998084    5 | 0.89998084    5 2.6499968 | 0.89998084    5 2.6499968
5 0.84119845    1 | 0.84119845    1 0.9205992 | 1.84645791    2 1.6154860

这两个函数都计算出正确的结果,但是mapply()在这种情况下更快 并且保留了数据框中观察的顺序。