我经常发现自己在同一个数据表上使用:=进行一长串的链式计算。例如,如下所示
test = data.table(1:10, 1:10, 1:10, 1:10)
test[, V1 := V1^2]
test[, V2 := V1*V2]
test[, V3 := V2/V3]
test[, V4 := sqrt(V3)]
test[, new := letters[V4]]必须在每一行都编写test[, ...] 1)需要更长的时间来输入(这不是一个大问题,我可以处理)。但是,更重要的是,它还在视觉上分散了对计算流程和内容的注意力。我更愿意写这样的东西
test[, {
V1 := V1^2
V2 := V1*V2
V3 := V2/V3
V4 := sqrt(V3)
new := letters[V4]
}]但这会抛出You have wrapped := with {} which is ok but then := must be the only thing inside {}的错误。
我知道我可以写
within(test, {
V1 = V1^2
V2 = V1*V2
V3 = V2/V3
V4 = sqrt(V3)
new = letters[V4]
})但是这会降低使用:=的效率。
我尝试编写一个函数来提供此功能。
with.dt = function(dt, expressions){
e = strsplit(expressions,'\n')
for (i in 1:length(e)){
dt[, eval(parse(text = e[i]))]
}
dt
}
with.dt(test, "
V1 := V1^2;
V2 := V1*V2;
V3 := V2/V3;
V4 := sqrt(V3);
new := letters[V4];
")但这不会更改data.table的内容
是否有任何语法可以在保留:=的按引用赋值属性的同时,保持within版本的整洁外观
发布于 2016-12-08 01:56:48
有几种不同的方法可以做到这一点。
此处使用的原始测试矩阵:
v1 v2
1: 1 3
2: 2 4首先,我们可以这样做:
test[,`:=`(v1 = v1^2,
v2 = v1*v2)输出:
v1 v2
1 3
4 8或者,如果我们想按顺序完成,我们可以使用Frank的hack。
test[, `:=`(v1 = v1 <- v1^2, v2 = v2 * v1)]输出:
v1 v2
1 3
4 16 或者,类似地我们可以运行以下代码:
test[,c("v1","v2") := list(v1^2,v1^2*v2)]输出:
v1 v2
1 3
4 16发布于 2016-12-08 03:15:48
我们可以使用一个接受表达式列表的函数:
with.dt = function(dt, expr){
for (j in 1:length(expr)) set(dt, , names(expr)[j], dt[, eval(expr[[j]])])
}
test = data.table(1:10, 1:10, 1:10, 1:10)
with.dt(test, expression(
V1 = V1^2,
V2 = V1*V2,
V3 = V2/V3,
V4 = sqrt(V3),
new = letters[V4]
))
# V1 V2 V3 V4 new
# 1: 1 1 1 1 a
# 2: 4 8 4 2 b
# 3: 9 27 9 3 c
# 4: 16 64 16 4 d
# 5: 25 125 25 5 e
# 6: 36 216 36 6 f
# 7: 49 343 49 7 g
# 8: 64 512 64 8 h
# 9: 81 729 81 9 i
#10: 100 1000 100 10 jhttps://stackoverflow.com/questions/41023553
复制相似问题