2

これは無害な単純な問題のように見えるかもしれませんが、実行には非常に長い時間がかかります。高速化やベクトル化などのアイデアは大歓迎です。

500 万行と 50 列の R データ フレームがあります。OriginalDataFrame

そのフレームからのインデックスのリスト: IndexList(55000 [ numIndex] 個の一意のインデックス)

時系列であるため、55,000 の一意のインデックスに対して約 5,000,000 行あります。

OriginalDataFrameによって注文されましたdataIndex。のすべてのインデックスが にIndexList存在しませんOriginalDataFrame。タスクは、存在するインデックスを見つけて、新しいデータ フレームを構築することです。FinalDataFrame

現在、次を使用してこのコードを実行していますlibrary(foreach):

FinalDataFrame <- foreach (i=1:numIndex, .combine="rbind") %dopar% {
  OriginalDataFrame[(OriginalDataFrame$dataIndex == IndexList[i]),]
}

これを 24 コアと 128GB RAM のマシンで実行しましたが、完了するまでに約 6 時間かかりました。

私は非常にばかげたことをしていますか、Rでこれを行うためのより良い方法はありますか?

4

3 に答える 3

3

これは、data.table と data.frame を比較する小さなベンチマークです。この場合の特別なデータ テーブルの呼び出しがわかっている場合、インデックスの設定コスト (比較的小さく、通常は複数回の呼び出しで償却される) を無視すると、約 7 倍高速になります。特別な構文を知らない場合は、少しだけ速くなります。(問題のサイズは、探索しやすいように元のサイズよりも少し小さいことに注意してください)

library(data.table)
library(microbenchmark)
options(digits = 3)

# Regular data frame
df <- data.frame(id = 1:1e5, x = runif(1e5), y = runif(1e5))

# Data table, with index
dt <- data.table(df)
setkey(dt, "id")

ids <- sample(1e5, 1e4)

microbenchmark(
  df[df$id %in% ids , ], # won't preserve order
  df[match(ids, df$id), ],
  dt[id %in% ids, ],
  dt[match(ids, id), ],
  dt[.(ids)]
)
# Unit: milliseconds
#                     expr   min    lq median    uq   max neval
#     df[df$id %in% ids, ] 13.61 13.99  14.69 17.26 53.81   100
#  df[match(ids, df$id), ] 16.62 17.03  17.36 18.10 21.22   100
#        dt[id %in% ids, ]  7.72  7.99   8.35  9.23 12.18   100
#     dt[match(ids, id), ] 16.44 17.03  17.36 17.77 61.57   100
#               dt[.(ids)]  1.93  2.16   2.27  2.43  5.77   100

私は当初、行名でもこれを行うことができるかもしれないと考えていました。これにより、ハッシュテーブルが構築され、効率的にインデックスが作成されると考えました。しかし、明らかにそうではありません。

df2 <- df
rownames(df2) <- as.character(df$id)
df2[as.character(ids), ],

microbenchmark(
  df[df$id %in% ids , ], # won't preserve order
  df2[as.character(ids), ],
  times = 1
)
# Unit: milliseconds
#                     expr    min     lq median     uq    max neval
#     df[df$id %in% ids, ]   15.3   15.3   15.3   15.3   15.3     1
# df2[as.character(ids), ] 3609.8 3609.8 3609.8 3609.8 3609.8     1
于 2013-08-07T13:44:29.267 に答える