I frequently find myself doing a long series of chained calculations using := on the same data table. For example, something like this
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]]
Having to write test[, ...] on every line 1) takes longer to type (not a big issue I can cope with that). But, more importantly, also distracts visually from the flow and content of the calculation. I would much rather write something like
test[, {
V1 := V1^2
V2 := V1*V2
V3 := V2/V3
V4 := sqrt(V3)
new := letters[V4]
}]
But this throws an error of You have wrapped := with {} which is ok but then := must be the only thing inside {}.
I know that I can write
within(test, {
V1 = V1^2
V2 = V1*V2
V3 = V2/V3
V4 = sqrt(V3)
new = letters[V4]
})
But this loses the efficiency of using :=
I tried writing a function to provide this ability
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];
")
But this does not change the content of the data.table
Is there any syntax that permits the neat look of the within version, while retaining the assign by reference property of :=?
There are a couple different ways to do this.
Original test matrix used here:
First, we can do something like this:
Output:
Or, if we want it done sequentially we can use Frank's hack.
Output:
Or, similarly we could run this:
Output: