在ddply()中,如果我想用自定义函数改变一个新列,那么必须事先定义自定义函数吗?

时间:2015-03-19 03:58:44

标签: r plyr anonymous-function

我们假设我有这个示例数据框:

df = data.frame(id=rep(1:2,each=5),v1=c(1:10),v2=c(1:10))

而且,比方说,我想创建一个新的列sumv1v2,它包含v1和v2的总和,仅当id = 1时(否则sumv1v2将为0)。

以下定义了预先定义的自定义函数,可以使用:

condisum = function(pid,pv1,pv2){
  if (pid[1]==1) {pv1+pv2}
  else {0}
}
df = ddply(df,"id",mutate,sumv1v2=condisum(id,v1,v2))

返回的数据帧是我需要的:

df
   id v1 v2 sumv1v2
1   1  1  1       2
2   1  2  2       4
3   1  3  3       6
4   1  4  4       8
5   1  5  5      10
6   2  6  6       0
7   2  7  7       0
8   2  8  8       0
9   2  9  9       0
10  2 10 10       0

但是我可以在ddply()内定义内联函数,就像匿名函数一样吗?我试过这个:

df = data.frame(id=rep(1:2,each=5),v1=c(1:10),v2=c(1:10))
df = ddply(df,"id",mutate,sumv1v2=function(pid,pv1,pv2){
  if (pid[1]==1) {pv1+pv2}
  else {0}
}(id,v1,v2))

我收到此错误消息:

Error: attempt to replicate an object of type 'closure'

我知道我无法将函数传递给mutate,并且应该传递一个表达式,这要归功于Gregor在这篇文章中的出色评论:

Use of ddply + mutate with a custom function?

所以我试图传递一个带有参数的匿名函数。这会成为一种表达吗?但我仍然有错误。

那么,是否可以不事先定义自定义函数,并在function()内使用ddply()定义它?

2 个答案:

答案 0 :(得分:1)

经过更多的试验,我终于意识到了这个问题。

现在可以使用以下内容:

df = data.frame(id=rep(1:2,each=5),v1=c(1:10),v2=c(1:10))
df = ddply(df,"id",mutate,sumv1v2=(function(pid,pv1,pv2){
  if (pid[1]==1) {pv1+pv2}
  else {0}
})(id,v1,v2))

记下匿名函数周围的新()。猜猜这最后把它变成了一个函数,并且用(id,v1,v2)来传递参数,整个事情最终变成了一个表达式。

以简单的形式,我试过这个:

x = function(y){y^2}(3)
x

和x返回:

function(y){y^2}(3)

但是,如果我添加()

x = (function(y) y^2)(3)
x

x返回:

[1] 9

答案 1 :(得分:1)

或者你可以在ddply调用的范围内定义函数,然后使用它。这可能使整个事情更容易阅读。

df <- data.frame(id=rep(1:2,each=5),v1=c(1:10),v2=c(1:10))

df <- ddply(
  df,
  "id",
  mutate,
  sumv1v2={
    f <- function(pid,pv1,pv2) {
      if (pid[1]==1) pv1 + pv2 
      else 0
    }
    f(id,v1,v2)
  }
)