16

full最後の列と1つの列を取得するデータフレームがありますvv次に、両方の列を可能な限り最速の方法で並べ替えたいと思います。fullcsvから読み込まれますが、これはテストに使用できます(リアリズムのためにいくつかのNAが含まれています)。

n <- 200000
full <- data.frame(A = runif(n, 1, 10000), B = floor(runif(n, 0, 1.9)))
full[sample(n, 10000), 'A'] <- NA
v <- 1

私はvここに1つありますが、実際には変更される可能性があり、full多くの列があります。


データフレーム、データテーブル、行列をそれぞれとで並べ替えてみorderました(このスレッドsort.listからいくつかのアイデアを取り入れました)。これらすべてのコード:

# DATA FRAME

ord_df <- function() {
  a <- full[c(v, length(full))]
  a[with(a, order(a[1])), ]
}

sl_df <- function() {
  a <- full[c(v, length(full))]
  a[sort.list(a[[1]]), ] 
}


# DATA TABLE

require(data.table)

ord_dt <- function() {
  a <- as.data.table(full[c(v, length(full))])
  colnames(a)[1] <- 'values'
  a[order(values)]
}

sl_dt <- function() {
 a <- as.data.table(full[c(v, length(full))])
 colnames(a)[1] <- 'values'
 a[sort.list(values)]
}


# MATRIX

ord_mat <- function() {
  a <- as.matrix(full[c(v, length(full))])
  a[order(a[, 1]), ] 
}

sl_mat <- function() {
  a <- as.matrix(full[c(v, length(full))])
  a[sort.list(a[, 1]), ] 
}

時間の結果:

         ord_df  sl_df    ord_dt   sl_dt   ord_mat sl_mat
Min.     0.230   0.1500   0.1300   0.120   0.140   0.1400
Median   0.250   0.1600   0.1400   0.140   0.140   0.1400
Mean     0.244   0.1610   0.1430   0.136   0.142   0.1450
Max.     0.250   0.1700   0.1600   0.140   0.160   0.1600

または使用microbenchmark(結果はミリ秒単位):

             min      lq       median   uq       max
1  ord_df() 243.0647 248.2768 254.0544 265.2589 352.3984
2  ord_dt() 133.8159 140.0111 143.8202 148.4957 181.2647
3 ord_mat() 140.5198 146.8131 149.9876 154.6649 191.6897
4   sl_df() 152.6985 161.5591 166.5147 171.2891 194.7155
5   sl_dt() 132.1414 139.7655 144.1281 149.6844 188.8592
6  sl_mat() 139.2420 146.8578 151.6760 156.6174 186.5416

データテーブルの注文が優先されるようです。はるかに高速なデータフレームを使用する場合を除いて、orderとの間にそれほど大きな違いはありません。sort.listsort.list

データテーブルのバージョンでvは、キーとして設定することも試みましたが(ドキュメントに従って並べ替えられているため)、内容vが整数ではないため、機能させることができませんでした。

さまざまな値に対して何度も実行する必要があるため、これを可能な限り高速化するのが理想的vです。このプロセスをさらにスピードアップする方法を誰かが知っていますか?Rcppまた、実装を試す価値があるでしょうか?ありがとう。


誰かに役立つ場合にタイミングをとるために使用したコードは次のとおりです。

sortMethods <- list(ord_df, sl_df, ord_dt, sl_dt, ord_mat, sl_mat)

require(plyr)
timings <- raply(10, sapply(sortMethods, function(x) system.time(x())[[3]]))
colnames(timings) <- c('ord_df', 'sl_df', 'ord_dt', 'sl_dt', 'ord_mat', 'sl_mat')
apply(timings, 2, summary) 

require(microbenchmark)
mb <- microbenchmark(ord_df(), sl_df(), ord_dt(), sl_dt(), ord_mat(), sl_mat())
plot(mb)
4

1 に答える 1

11

この種のものを編集として入れる方が良いかどうかはわかりませんが、答えのように見えるので、ここで行います。更新されたテスト機能:

n <- 1e7
full <- data.frame(A = runif(n, 1, 10000), B = floor(runif(n, 0, 1.9)))
full[sample(n, 100000), 'A'] <- NA

fdf <- full
fma <- as.matrix(full)
fdt <- as.data.table(full)
setnames(fdt, colnames(fdt)[1], 'values')

# DATA FRAME
ord_df <- function() { fdf[order(fdf[1]), ] }
sl_df <- function() { fdf[sort.list(fdf[[1]]), ] }

# DATA TABLE
require(data.table)
ord_dt <- function() { fdt[order(values)] }

key_dt <- function() {
  setkey(fdt, values) 
  fdt
}

# MATRIX
ord_mat <- function() { fma[order(fma[, 1]), ] }
sl_mat <- function() { fma[sort.list(fma[, 1]), ] }

結果(別のコンピューター、R 2.13.1およびdata.table1.8.2を使用):

         ord_df  sl_df   ord_dt  key_dt  ord_mat sl_mat
Min.     37.56   20.86   2.946   2.249   20.22   20.21
1st Qu.  37.73   21.15   2.962   2.255   20.54   20.59
Median   38.43   21.74   3.002   2.280   21.05   20.82
Mean     38.76   21.75   3.074   2.395   21.09   20.95
3rd Qu.  39.85   22.18   3.151   2.445   21.48   21.42
Max.     40.36   23.08   3.330   2.797   22.41   21.84

並べ替え

したがって、data.tableが明らかに勝者です。キーの使用は注文よりも高速であり、構文も優れていると私は主張します。みんな助けてくれてありがとう。

于 2012-07-19T22:43:28.193 に答える