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