DT
という名前の列を持つdata.tableRF
と、下線_
が含まれる多くの列があります。下線付きのすべての列をループして、そこからRF
列を減算したいと思います。しかし、私は立ち往生しています。 :=
のdata.table
演算子のRHSのすべてが、動的変数では機能しないようです。
これが私のDT
と必要な出力(ハードコードされた)です:
library(data.table)
DT <- data.table(RF = 1:10,
S_1 = 11:20,
S_2 = 21:30)
#Desired output
DT[ , S_1 := S_1 - RF]
DT[ , S_2 := S_2 - RF]
DT
RF S_1 S_2
[1,] 1 10 20
[2,] 2 10 20
[3,] 3 10 20
...
ただし、これをより柔軟にする必要があります。つまり、名前に「_」が含まれるすべての列をループして、RF
を減算します。
#1. try: Does not work; Interestingly, the i on the LHS of := is interpreted as the column i, but on the RHS of
#:= it is interpreted as 2 and 3, respectively
for (i in grep("_", names(DT))){
DT[ , i:= i - 1, with=FALSE]
}
DT
RF S_1 S_2
[1,] 1 1 2
[2,] 2 1 2
[3,] 3 1 2
...
#2. try: Work with parse and eval
for (i in grep("_", names(DT), value=TRUE)){
DT[ , eval(parse(text=i)):= eval(parse(text=i)) - RF]
}
#Error in eval(expr, envir, enclos) : object 'S_1' not found
それを行う方法のヒントは素晴らしいでしょう。
編集:質問を投稿するとすぐに、私は自分自身に思いました:なぜあなたはそもそも:=
演算子を使っているのですか、そして確かに、私はそうする必要がないことに気づきました。これは機能し、ループは必要ありません。
DT[, grep("_", names(DT)), with=FALSE] - DT[, RF]
そのために残念。ただし、:=
演算子を使用したアプローチが機能しない理由にまだ関心があるため、質問は開いたままにしておきます。だから多分誰かがそこで私を助けることができます。
あなたは2回目の試みで正しい軌道に乗っていました。これは、substitute
を使用して、'j'
のDT[ , j ]
引数として渡される式を作成するアプローチです。
for (i in grep("_", names(DT), value=TRUE)){
e <- substitute(X := X - RF, list(X = as.symbol(i)))
DT[ , eval(e)]
}
DT
# RF S_1 S_2
# [1,] 1 10 20
# [2,] 2 10 20
# [3,] 3 10 20
# [4,] 4 10 20
# [5,] 5 10 20
または今(1年後)with=FALSE
が:=
のLHSに適用されますok:
for (i in grep("_", names(DT), value=TRUE))
DT[, i:=get(i)-RF, with=FALSE]
またはwith=FALSE
は、LHSを記号ではなく式にすることで回避できます。
for (i in grep("_", names(DT), value=TRUE))
DT[, (i):=get(i)-RF]
質問を投稿した後に残念ながら発見した回避策は次のとおりです。
DT[, grep("_", names(DT)), with=FALSE] - DT[, RF]
これは、保持したい追加の列がある、より複雑な設定でも機能しますが、追加の労力が必要です。
library(data.table)
DT <- data.table(RF = 1:10,
S_1 = 11:20,
S_2 = 21:30,
addCol = rnorm(10)) #Column that should not be subtracted by RF, but still kept in DT
DT <- cbind(DT[, grep("_", names(DT)), with=FALSE] - DT[, RF], addCol = DT[, addCol])
質問と回答をありがとうございます。 私は同様のタスクのために一時変数の助けを借りてソリューションを使用していました。
_varnames <- grep("_", names(DT), value=TRUE) for (i in varnames) { DT[, ".tmp"] <- DT[, i, with = F] DT[, i := .tmp - RF, with = F] if (i == tail(varnames, 1)) DT[, ".tmp"] <- NULL }
_
唯一のリスクは、既存の変数_.tmp
_を上書きすることです。
すごい。 set()
は強力です。
_varnames <- grep("_", names(DT), value=TRUE)
set(DT, j = varnames, value = DT[, varnames, with = F] - DT[, RF])
_