动态添加作为先前列功能的列的优雅方式

时间:2017-10-30 13:12:06

标签: r data.table

有没有更好的方法来实现以下结果? 我通常使用这种编码方法在许多列上操作(想象v2有20 +列,所以我需要一种动态方法来构建新列)

set.seed(1)
dt <- data.table(m = 1:10, v1 = rnorm(10, 1), v2 = rnorm(10, 1), v3 = rnorm(10, 1))

run_across <- function(x, y = "m", z = c("v1")) {
#  browser()
x[,c(paste0(y, ".", z), paste0(y, ".div.", z)) := list(get(y) * get(z), get(y) / get(z))]
}

# works fine for an individual case:
run_across(dt)

# Error: param z returns the values of column v1:
dt[, lapply(X=.SD, FUN = run_across, x = dt, y = "m"), .SDcols = paste0("v", 1:3)]

# This has desired result, but is there a more elegant approach?
invisible(lapply(paste0("v", 1:3), run_across, x = dt, y = "m"))

1 个答案:

答案 0 :(得分:2)

首先,&#34;优雅&#34;从我的角度来看,这是一个非常主观的术语,对评估代码并没有多大帮助。

其次,OP提供给自己的方法并不坏,使用sinlge lapply - 来电。

第三,我能想到的最好的事情就是让这个更优雅&#34; (在R-like或简单的意义上)操作,是在运行自定义函数之前将数据转换为长格式:

dt <- melt(dt, id.vars = "m")
run_across(dt, y = "m", z = "value")

这意味着,您可以在一次调用run_across的情况下完成此操作而无需循环播放。

如果您之后需要转换为宽格式,可以使用dcast

dcast(dt, m ~ variable, value.var = c("value","m.value", "m.div.value"))