Самый быстрый по сортировке столбцов в R
У меня есть кадр данных 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)
Ответы
Ответ 1
Я не знаю, лучше ли вставлять такие вещи в качестве редактирования, но это похоже на ответ, так что вот так. Обновленные тестовые функции:
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.table
1.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
![Sorting]()
Таким образом, data.table является явным победителем. Использование ключа быстрее, чем упорядочение, и с хорошим синтаксисом, я бы спорил. Спасибо за помощь всем.