data.tableでcolnamesを使うと怒られる
data.table型にしたデータに対してcolnames関数を使うとぐわーっと警告が出る。
> library(data.table) > iris <- as.data.table(iris) > colnames(iris) <- colnames(iris) Warning message: In `names<-.data.table`(`*tmp*`, value = value) : The colnames(x)<-value syntax copies the whole table. This is due to <- in R itself. Please change to setnames(x,old,new) which does not copy and is faster. See help('setnames'). You can safely ignore this warning if it is inconvenient to change right now. Setting options(warn=2) turns this warning into an error, so you can then use traceback() to find and change your colnames<- calls.
どうやらcolnames(なんたら)<-はオブジェクトをコピーしてしまうのでコピーせずしかも速いsetnames関数を使えとのことらしい。
colnamesでオブジェクトコピーするとかなにそれこわい。
オブジェクトのコピーが起きているかどうかはtracemem関数を使って確認できる。
実際に試してみる。
> library(data.table) > iris <- as.data.table(iris) > tracemem(iris) [1] "<0x000000000b9fb1d8>" > colnames(iris) <- colnames(iris) # コピーされている tracemem[0x000000000b9fb1d8 -> 0x000000000b9fd450]: tracemem[0x000000000b9fd450 -> 0x00000000105d77e8]: colnames<- Warning message: In `names<-.data.table`(`*tmp*`, value = value) : The colnames(x)<-value syntax copies the whole table. This is due to <- in R itself. Please change to setnames(x,old,new) which does not copy and is faster. See help('setnames'). You can safely ignore this warning if it is inconvenient to change right now. Setting options(warn=2) turns this warning into an error, so you can then use traceback() to find and change your colnames<- calls. > setnames(iris, colnames(iris)) # コピーされていない
確かにコピーされている。Rでメモリ制限ぎりぎりのデータを扱うときはこういうのも命取りになるのか。こわい。
参考資料
data.tableについてはRjpwikiに間瀬先生のまとめがある(一時コピーがない旨の記述もある)。
http://www.okada.jp.org/RWiki/?R%20%A5%D0%A1%BC%A5%B8%A5%E7%A5%F33%A4%CB%B4%F3%A4%BB%A4%C6#wc16f06d
tracememやメモリ周りの話については以下の資料が参考になる。
日本語のブログ記事(わかりやすい)
http://www.singularpoint.org/blog/r/r-call-by-value-or-reference-2/
Hadley Wickhamのメモリー覚書
http://adv-r.had.co.nz/memory.html