46

の名前を として保存しましdata.tablevector

library(data.table)
set.seed(42)
DT <- data.table(x = runif(100), y = runif(100))
names1 <- names(DT)

私が知る限り、これは単純なバニラ文字ベクトルです。

str(names1)
# chr [1:2] "x" "y"

class(names1)
# [1] "character"

dput(names1)
# c("x", "y")

ただし、これは通常の文字ベクトルではありません。魔法の文字ベクトルです!に新しい列を追加するとdata.table、このベクトルが更新されます!

DT[ , z := runif(100)]
names1
# [1] "x" "y" "z"

これは代入による更新方法と関係があることは知っていますが、の名前のコピーを作成すること:=を期待しているため、これはまだ魔法のように思えます。<-data.table

名前を でラップすることでこれを修正できますc()

library(data.table)
set.seed(42)
DT <- data.table(x = runif(100), y = runif(100))

names1 <- names(DT)
names2 <- c(names(DT))
all.equal(names1, names2)
# [1] TRUE

DT[ , z := runif(100)]
names1
# [1] "x" "y" "z"

names2
# [1] "x" "y"

私の質問は2つです:

  1. の名前のnames1 <- names(DT)コピーを作成しないのはなぜですか? 他の例では、 s とs の両方のコピーを作成するdata.tableことが明示的に警告されます。<-data.tabledata.frame
  2. names1 <- names(DT)とはどう違いnames2 <- c(names(DT))ますか?
4

1 に答える 1

44

更新: これは?copy、バージョン 1.9.3 のドキュメントに追加されました。NEWSより

  1. ?copy独自のヘルプ ページに移動し、参照による更新の結果として参照によって変更されないようにするdt_names <- copy(names(DT))必要があることを文書化しました(例: 参照による新しい列の追加)。#512を閉じます。この SO の質問については Zach に、この SO の質問についてuser1971988 に感謝します。dt_namesDT

あなたの最初の質問の一部は、あなたが演算子について本当に何を意味するのか(少なくとも のコンテキストでは)、特に次の部分についてには少し不明確になります。 .tables と data.frames。<-data.table

ですから、実際の質問に答える前に、ここで簡単に触れておきます。data.tablea <-(代入)の場合、単にa をコピーするには十分ではありませんdata.table。例えば:

DT <- data.table(x = 1:5, y= 6:10)
# assign DT2 to DT
DT2 <- DT # assign by reference, no copy taken.
DT2[, z := 11:15]
# DT will also have the z column

を作成する場合はcopy、コマンドを使用して明示的に言及する必要がありますcopy

DT2 <- copy(DT) # copied content to DT2
DT2[, z := 11:15] # only DT2 is affected

CauchyDistributedRV から、あなたが意味することはnames(dt) <- .、警告が発生する割り当てであることを理解しています。そのままにしておきます。


さて、あなたの最初の質問に答えるために:names1 <- names(DT)も同様に振る舞うようです. 私は今までこれについて考えていませんでした/知りませんでした。この.Internal(inspect(.))コマンドは、次の場合に非常に役立ちます。

.Internal(inspect(names1))
# @7fc86a851480 16 STRSXP g0c7 [MARK,NAM(2)] (len=2, tl=100)
#   @7fc86a069f68 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "x"
#   @7fc86a0f96d8 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "y"

.Internal(inspect(names(DT)))
# @7fc86a851480 16 STRSXP g0c7 [MARK,NAM(2)] (len=2, tl=100)
#   @7fc86a069f68 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "x"
#   @7fc86a0f96d8 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "y"

ここでは、それらが同じメモリ位置を指していることがわかります@7fc86a851480truelengthのもnames1100 です (これはデフォルトで に割り当てられています。これdata.tableを確認?alloc.colしてください)。

truelength(names1)
# [1] 100

したがって、基本的に、割り当てnames1 <- names(dt)は参照によって行われるようです。つまり、names1dt の列名ポインターと同じ場所を指しています。

2番目の質問に答えるには:連結操作による内容の結果が異なるかどうかのチェックがないため、コマンドc(.)はコピーを作成するようです。つまり、操作はベクトルの内容を変更できるため、内容が変更されているかどうかを確認せに、すぐに「コピー」が作成されます。c(.)

于 2013-04-09T22:24:15.007 に答える