我有一个数据框 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
我这里有一个变量v
,但实际上它可能会改变,而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.list
之间并没有太大的区别,除非使用sort.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)
ord_df
,不需要使用with
。你的速度差异是因为对数据框进行排序order(a[1])
而不是向量order(a[[1]])
;order(a[[1]])
就像sort.list(a[[1]])
。如果要排序的列实际上是整数值,则sort.list(..., method="radix")
很快(比 data.table 更快?)。 - Martin Morgandata.table
使用sort.list(...,method="radix")
。如?setkey
中所述。 - Matt Dowle