2012-07-27 6 views
88

data.tableを使用して複数の列に割り当てる最良の方法は何ですか?たとえば:複数の列を割り当てるには:data.table内でグループ単位で

f <- function(x) {c("hi", "hello")} 
x <- data.table(id = 1:10) 

が、私はこのような何かをしたいと思います(もちろん、この構文が正しくありません):

x[ , (col1, col2) := f(), by = "id] 

そして私は、変数に名前を持つ多くの列を持っていることを拡張する(たとえばcolumn_names)と私がやりたい:

x[ , col_names := another_f(), by = "id", with = FALSE] 

このような何かをするための正しい方法は何ですか?

+1

これは、回答されているように見えます: http://stackoverflow.com/questions/11308754/add-multiple-columns-to-r-data- table-in-one-function-call – Alex

+0

Alex、その答えは近いですが、@Christoph_Jは正しいと言えば 'by'と組み合わせて動作しないようです。あなたの質問へのリンクは、[FR#2120](https://r-forge.r-project.org/tracker/index.php?func=detail&aid=2120&group_id=240&atid=978)に追加されました。 of:= "ので、再訪するのを忘れることはありません。 –

答えて

106

これはR-Forgeのv1.8.3で動作するようになりました。それを強調していただきありがとうございます!

x <- data.table(a = 1:3, b = 1:6) 
f <- function(x) {list("hi", "hello")} 
x[ , c("col1", "col2") := f(), by = a][] 
# a b col1 col2 
# 1: 1 1 hi hello 
# 2: 2 2 hi hello 
# 3: 3 3 hi hello 
# 4: 1 4 hi hello 
# 5: 2 5 hi hello 
# 6: 3 6 hi hello 

x[ , c("mean", "sum") := list(mean(b), sum(b)), by = a][] 
# a b col1 col2 mean sum 
# 1: 1 1 hi hello 2.5 5 
# 2: 2 2 hi hello 3.5 7 
# 3: 3 3 hi hello 4.5 9 
# 4: 1 4 hi hello 2.5 5 
# 5: 2 5 hi hello 3.5 7 
# 6: 3 6 hi hello 4.5 9 

mynames = c("Name1", "Longer%") 
x[ , (mynames) := list(mean(b) * 4, sum(b) * 3), by = a] 
#  a b col1 col2 mean sum Name1 Longer% 
# 1: 1 1 hi hello 2.5 5 10  15 
# 2: 2 2 hi hello 3.5 7 14  21 
# 3: 3 3 hi hello 4.5 9 18  27 
# 4: 1 4 hi hello 2.5 5 10  15 
# 5: 2 5 hi hello 3.5 7 14  21 
# 6: 3 6 hi hello 4.5 9 18  27 


x[ , mynames := list(mean(b) * 4, sum(b) * 3), by = a, with = FALSE][] # same 
# a b col1 col2 mean sum Name1 Longer% 
# 1: 1 1 hi hello 2.5 5 10  15 
# 2: 2 2 hi hello 3.5 7 14  21 
# 3: 3 3 hi hello 4.5 9 18  27 
# 4: 1 4 hi hello 2.5 5 10  15 
# 5: 2 5 hi hello 3.5 7 14  21 
# 6: 3 6 hi hello 4.5 9 18  27 

x[ , get("mynames") := list(mean(b) * 4, sum(b) * 3), by = a][] # same 
# a b col1 col2 mean sum Name1 Longer% 
# 1: 1 1 hi hello 2.5 5 10  15 
# 2: 2 2 hi hello 3.5 7 14  21 
# 3: 3 3 hi hello 4.5 9 18  27 
# 4: 1 4 hi hello 2.5 5 10  15 
# 5: 2 5 hi hello 3.5 7 14  21 
# 6: 3 6 hi hello 4.5 9 18  27 

x[ , eval(mynames) := list(mean(b) * 4, sum(b) * 3), by = a][] # same 
# a b col1 col2 mean sum Name1 Longer% 
# 1: 1 1 hi hello 2.5 5 10  15 
# 2: 2 2 hi hello 3.5 7 14  21 
# 3: 3 3 hi hello 4.5 9 18  27 
# 4: 1 4 hi hello 2.5 5 10  15 
# 5: 2 5 hi hello 3.5 7 14  21 
# 6: 3 6 hi hello 4.5 9 18  27 
+0

この回答と例をありがとう。 2つの行を持つ1つの列ではなく、dim出力から各objectNameの2つの列を取得するには、次の行をどのように変更する必要がありますか? = itemName] '(私は' data.table'を使用しています。)1.8。data.table(objectName = ls())[、c( "rows"、 "cols"):= dim(get(objectName) 11) – dnlbrky

+0

@dnlbrky 'dim'はベクトルを返しますので、' list'型に変換するとそれを回転させるはずです。例えば'[、c(" rows "、" cols "):= as.list(dim(get(objectName)))、by = objectNa me]'問題は、 'as.list'が呼び出しオーバーヘッドを持ち、小さなベクトルをコピーすることです。グループの数が増えるにつれて効率が問題になる場合は、私たちにお知らせください。 –

+0

ありがとう@Matt_Dowle。私は 'list'を試しましたが、' as.list'は試していませんでした。スピードは問題ではありません。特定の数の列または行を持つ環境内のオブジェクトをすばやく見つける方法が必要でした。これは話題ですが、NCOLを 'tables()'に追加するとどう思いますか? – dnlbrky

関連する問題