如何传递列变量来应用函数?

时间:2013-01-21 15:05:41

标签: r

我有data.frame

  id  |  amount1  | amount2  |  day1  |  day2
 ---------------------------------------------
  A   |    10     |    32    |   0    |   34
  B   |    54     |    44    |   8    |   43
  C   |    45     |    66    |   16   |   99    

df <- data.frame(id=c('A','B','C'), amount1=c(10,54,45), amount2=c(32,44,66),  day1=c(0,8,16), day2=c(34,43,99))

我希望apply一个函数

df$res <-  apply(df, 1, myfunc)

其中

myfunc <- function(x,y) sum(x) * mean(y)

只有我想将列变量作为参数传递给函数,因此它基本上应该读取

 apply(df, 1, myfunc, c(amount1, amount2), c(day1, day2))

第一行是

myfunc(c(10,32),c(0,34))
# [1] 714

可以这样做吗?

3 个答案:

答案 0 :(得分:4)

data.table解决方案。

require(data.table)
dt <- data.table(df) # don't depend on `id` column as it may not be unique
# instead use 1:nrow(dt) in `by` argument
dt[, res := myfunc(c(amount1,amount2), c(day1, day2)), by=1:nrow(dt)]
> dt
#    id amount1 amount2 day1 day2    res
# 1:  A      10      32    0   34  714.0
# 2:  B      54      44    8   43 2499.0
# 3:  C      45      66   16   99 6382.5

当您有很多days列时,您希望获取mean并乘以sumamount1的{​​{1}} ,然后我会以这种方式做,而不使用amount2。但如果你真的需要一个函数,那么实现一个应该是直截了当的。

myfunc

答案 1 :(得分:3)

像这样:

df$res <- apply(df, 1, function(x) myfunc(as.numeric(x[c("amount1", "amount2")]),
                                          as.numeric(x[c("day1", "day2")])))

但请考虑plyr::adply作为替代方案:

library(plyr)
adply(df, 1, transform, res = myfunc(c(amount1, amount2), c(day1, day2)))
#   id amount1 amount2 day1 day2    res
# 1  A      10      32    0   34  714.0
# 2  B      54      44    8   43 2499.0
# 3  C      45      66   16   99 6382.5

答案 2 :(得分:1)

这适用于您的示例。也许同样的技术可以用于真正的问题:

> apply(df[-1], 1, function(x) myfunc(x[1:2], x[3:4]))
## [1]  714.0 2499.0 6382.5

正如flodel所指出的,最好使用其中一个子集化操作的名称,以确保只使用这些列进行应用。必须使用子集来防止apply传递的向量转换为字符,并明确指定列意味着数据框中的其他列不会导致此问题。

apply(df[c("amount1", "amount2", "day1", "day2")], 1, 
      function(x) myfunc(x[1:2], x[3:4])
     )

在实践中,我更有可能编写类似这样的代码:

amount <- c("amount1", "amount2")
day    <- c("day1", "day2")

df$res <- apply(df[c(amount, day)], 1, function(x) myfunc(x[amount], x[day]))