Another excellent method from Martin Morgan without any usage of external packages in Fastest way to select i-th highest value from row and assign to new column:
matrix(a[order(row(a), a)], ncol=ncol(a), byrow=TRUE)
There is also an equivalent for sorting by columns under comments in the same link.
Timing code using same data as Craig:
set.seed(1)
a <- matrix(runif(9e7),ncol=300)
use_for <- function(){
sorted3 <- a
for(i in seq_len(nrow(a)))
sorted3[i,] <- sort.int(a[i,], method='quick')
sorted3
}
microbenchmark::microbenchmark(times=3L,
t(apply(a,1,sort)),
t(apply(a,1,sort.int, method='quick')),
use_for(),
Rfast::rowSort(a),
t(apply(a,1,grr::sort2)),
mmtd=matrix(a[order(row(a), a)], ncol=ncol(a), byrow=TRUE)
)
Timings:
Unit: seconds
expr min lq mean median uq max neval
t(apply(a, 1, sort)) 24.233418 24.305339 24.389650 24.377260 24.467766 24.558272 3
t(apply(a, 1, sort.int, method = "quick")) 17.024010 17.156722 17.524487 17.289433 17.774726 18.260019 3
use_for() 13.384958 13.873367 14.131813 14.361776 14.505241 14.648705 3
Rfast::rowSort(a) 3.758765 4.607609 5.136865 5.456452 5.825914 6.195377 3
t(apply(a, 1, grr::sort2)) 9.810774 9.955199 10.310328 10.099624 10.560106 11.020587 3
mmtd 6.147010 6.177769 6.302549 6.208528 6.380318 6.552108 3
And to present a more complete picture, another test for character class (excluding Rfast::rowSort
as it cannot handle character class):
set.seed(1)
a <- matrix(sample(letters, 9e6, TRUE),ncol=300)
microbenchmark::microbenchmark(times=1L,
t(apply(a,1,sort)),
t(apply(a,1,sort.int, method='quick')),
use_for(),
#Rfast::rowSort(a),
t(apply(a,1,grr::sort2)),
mmtd=matrix(a[order(row(a), a, method="radix")], ncol=ncol(a), byrow=TRUE)
)
Timings:
Unit: milliseconds
expr min lq mean median uq max neval
t(apply(a, 1, sort)) 14848.4356 14848.4356 14848.4356 14848.4356 14848.4356 14848.4356 1
t(apply(a, 1, sort.int, method = "quick")) 15061.0993 15061.0993 15061.0993 15061.0993 15061.0993 15061.0993 1
use_for() 14144.1264 14144.1264 14144.1264 14144.1264 14144.1264 14144.1264 1
t(apply(a, 1, grr::sort2)) 1831.1429 1831.1429 1831.1429 1831.1429 1831.1429 1831.1429 1
mmtd 440.9158 440.9158 440.9158 440.9158 440.9158 440.9158 1
Head to head:
set.seed(1)
a <- matrix(sample(letters, 9e7, TRUE),ncol=300)
microbenchmark::microbenchmark(times=1L,
t(apply(a,1,grr::sort2)),
mmtd=matrix(a[order(row(a), a, method="radix")], ncol=ncol(a), byrow=TRUE)
)
Timings:
Unit: seconds
expr min lq mean median uq max neval
t(apply(a, 1, grr::sort2)) 19.273225 19.273225 19.273225 19.273225 19.273225 19.273225 1
mmtd 3.854117 3.854117 3.854117 3.854117 3.854117 3.854117 1
R version:
R version 4.0.3 (2020-10-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18363)