19

ここSOで同様の問題への参照をいくつか読みましたが、まだ解決策を見つけることができず、data.tableだけを使用して次のことを行う方法があるかどうか疑問に思っています。

簡単な例を使用しますが、実際には、データ テーブルには var1、var2、... var1000 などのような 1000 を超える列があります。

dt <- data.table(uid=c("a","b"), var1=c(1,2), var2=c(100,200))

reshapeのmelt関数に似た出力を得ることができるソリューションを探しています-

> melt(dt, id=c("uid"))
uid variable value
1   a     var1     1
2   b     var1     2
3   a     var2   100
4   b     var2   200

つまり、uid を除くすべての列が 1 つの列の下にリストされ、対応する値が隣接する列に表示されます。リストなどの組み合わせでこれを試しましたが、明らかなものが欠けている可能性があります。

dt のすべての uid は一意です。

前もって感謝します。

4

3 に答える 3

19

data.table の形状を変更するには、次のことを試してください。

dt[, list(variable = names(.SD), value = unlist(.SD, use.names = F)), by = uid]

構文のコストはそれだけの価値があります。関数は非常に高速に実行されます。

于 2013-08-26T18:24:13.213 に答える
6

恥知らずな自己宣伝

melt_私のパッケージから試してみてくださいKmiscmelt_は基本的に を書き直したreshape2:::melt.data.frameものであり、面倒な作業のほとんどは C で行われ、迅速な実装のためにできるだけ多くのコピーと型強制を回避します。

例:

## devtools::install_github("Kmisc", "kevinushey")
library(Kmisc)
library(reshape2)
library(microbenchmark)
n <- 1E6
big_df <- data.frame( stringsAsFactors=FALSE,
  x=sample(letters, n, TRUE),
  y=sample(LETTERS, n, TRUE),
  za=rnorm(n),
  zb=rnorm(n),
  zc=rnorm(n)
)
all.equal(
  melt <- melt(big_df, id.vars=c('x', 'y')),
  melt_ <- melt_(big_df, id.vars=c('x', 'y'))
)
## we don't convert the 'variable' column to factor by default
## if we do, we see they're identical
melt_$variable <- factor(melt_$variable)
stopifnot( identical(melt, melt_) )
microbenchmark( times=5,
  melt=melt(big_df, id.vars=c('x', 'y')),
  melt_=melt_(big_df, id.vars=c('x', 'y'))
)

私にくれます

Unit: milliseconds
  expr       min        lq    median         uq       max neval
  melt 916.40436 931.60031 999.03877 1102.31090 1160.3598     5
 melt_  61.59921  78.08768  90.90615   94.52041  182.0879     5

運が良ければ、これはデータに対して十分に高速です。

于 2013-08-30T07:02:42.793 に答える