web-dev-qa-db-ja.com

特定のdata.tableの列と行に値を割り当てる

このすばらしいパッケージをまだ理解しています...このエラーの理由を誰かに説明していただけませんか?ありがとう!

library(data.table)

DT <- data.table(id   = LETTERS,
                 var1 = rnorm(26),
                 var2 = rnorm(26))

> DT[2, list(var1, var2)]
            var1          var2
1: -0.8628479332 -0.2367492928
> DT[2, c(var1, var2)]
[1] -0.8628479332 -0.2367492928
> 
> DT[2, list(var1, var2)] <- DT[8, list(var1, var2)]
Error in `[<-.data.table`(`*tmp*`, 2, list(var1, var2), value = list(var1 = -0.394006912428776,  : 
  object 'var1' not found
> DT[2, c(var1, var2)] <- DT[8, c(var1, var2)]
Error in `[<-.data.table`(`*tmp*`, 2, c(var1, var2), value = c(-0.394006912428776,  : 
  object 'var1' not found
19
Michele

最初に、効率のために_:=_ではなく_[<-_を使用することをお勧めします。 _[<-_は、ほとんどが後方互換性のために提供されています。そこで、まず_:=_を効率的に使用して目的を達成する方法を説明します。 _:=_は参照による代入です(データをコピーせずにdata.tableを更新するため、extremelyfast)。

_require(data.table)
DT <- data.table(x = 1:5, y = 6:10, z = 11:15)
_

「y」の2行目を「y」の5行目の行に変更するとします。

_DT[2, y := DT[5, y]] 
_

または同等に

_DT[2, `:=`(y = DT[5, y])]
_

both "y"と "z"の2行目を5行目の対応するエントリの2行目に変更するとします。

_DT[2, c("y", "z") := as.list(DT[5, c(y, z)])]
_

または同等に

_DT[2, `:=`(y = DT[5, y], z = DT[5, z])]
_

_[<-_を使用して割り当てる方法を示すために(これは明らかに推奨されませんが)、次のように実行できます。

_DT <- data.table(x = 1:5, y = 6:10, z = 11:15)
DT[1, c("y", "z")] <- as.list(DT[5, c(y, z)])
_

または同等に、列番号を渡すこともできます。

_DT[1, 2:3] <- as.list(DT[5, c(y, z)])
_

お役に立てれば。


編集1

エラーが発生する理由について:

最初に、RHSは、割り当てられる列が複数ある場合、_[<-data.table_のリストでなければなりません。

次に、_<-_の左側のj引数は、data.tableの環境内では評価されません。したがって、jの値が何であるかを知る必要があります。また、_var1_および_var2_(二重引用符なしを指定すると、それらは文字ベクトルになります)を提供するため、変数と見なされます。したがって、変数_var1_および_var2_をチェックしますが、data.table内の列を変数として「認識」しないため(RHSで割り当てなどを行うときに通常行うように) _<-_)の場合、親環境で同じ変数を検索します。これは、それらが見つからないグローバル環境であるため、エラーが発生します。例:これを行う:

_y <- "y"
z <- "z"
# And now try your second case: 
DT[2, c(y, z)] <- as.list(DT[5, c(y, z)])
# the left side takes values from the assignments you made above
# the right side y and z are evaluated within the environment of your data.table
# and so it sees the columns y and z as variables and their values are picked accordingly
_

3番目に、_[<-data.table_関数は、atomic引数にj(ベクトル)型のみを受け入れます。したがって、最初の割り当てDT[2, list(var1, var2)] <- DT[8, list(var1, var2)]を正しく実行すると、エラーが発生します。

_y <- "y"
z <- "z"
DT[2, list(y, z)] <- as.list(DT[5, c(y, z)])

# Error in `[<-.data.table`(`*tmp*`, 2, list(y, z), value = list(10L, 15L)) : 
#   j must be atomic vector, see ?is.atomic
_

お役に立てれば。


編集2

_[<-_を実行するとdata.tableのコピーが作成されるが、_:=_を実行すると作成されないことを示すために、

_DT <- data.table(x = 1:5, y = 6:10, z = 11:15)
tracemem(DT)
# [1] "<0x7fbefb89b580>"

DT[1, c("y", "z") := list(100L, 110L)]
tracemem(DT)
# [1] "<0x7fbefb89b580>"

DT[2, c("y", "z")] <- list(200L, 201L)
# tracemem[0x7fbefacc4fa0 -> 0x7fbefd297838]: # copied, inefficient
_
35
Arun