R中的列排序最快

Fis*_*ist 15 r data.table

我有一个数据框full,我想从中获取最后一列和一列v.然后我想以v最快的方式对两列进行排序.full从csv读入,但这可以用于测试(包括一些现实主义的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
Run Code Online (Sandbox Code Playgroud)

我在v这里有一个,但实际上它可以改变,并full有很多专栏.


我尝试过对数据框,数据表和矩阵进行排序ordersort.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]), ] 
}
Run Code Online (Sandbox Code Playgroud)

时间结果:

         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
Run Code Online (Sandbox Code Playgroud)

或使用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
Run Code Online (Sandbox Code Playgroud)

似乎订购数据表获胜.除了使用速度更快的数据帧之外,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)
Run Code Online (Sandbox Code Playgroud)

Fis*_*ist 9

我不知道将这种东西放在编辑中是否更好,但它似乎更像是答案,所以这里会做.更新的测试功能:

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]), ] }
Run Code Online (Sandbox Code Playgroud)

结果(使用不同的计算机,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
Run Code Online (Sandbox Code Playgroud)

排序

所以data.table是明显的赢家.使用密钥比排序更快,并且具有更好的语法,我认为.感谢大家的帮助.