我有一个包含几百万行和大约 40 列的矩阵。
我想对每一行中的元素进行排序,使它们的值递减。因此,每一行中具有最高值的元素应该在第一列中。
为此,我可以使用
apply
功能。例如:
set.seed(1)
mm <- replicate(10, rnorm(20)) #random matrix with 20 rows and 10 columns
mm.sorted <- apply(mm,1,sort,decreasing=T)
但是当我对一个非常大的矩阵执行此操作时,这种方法需要很长时间。
我想知道是否有不同的方法可以加快行中元素的排序。
使用并行包加速
library(parallel)
data<-matrix(rnorm(1000000*40,0,10),ncol=40)
cl <- makeCluster(8) # 8 is the number of CPU
system.time({
parApply(cl,data,1,sort,decreasing=T)
})
user system elapsed
9.68 10.11 29.87
stopCluster(cl)
你可以使用 package data.table:
set.seed(1)
mm <- matrix(rnorm(1000000*40,0,10),ncol=40)
library(data.table)
system.time({
d <- as.data.table(mm)
d[, row := .I]
d <- melt(d, id.vars = "row") #wide to long format
setkey(d, row, value) #sort
d[, variable := paste0("V", ncol(mm):1)] #decreasing order
#back to wide format and coerce to matrix
msorted <- as.matrix(dcast(d, row ~ variable)[, row := NULL])
})
#user system elapsed
#4.96 0.59 5.62
如果你可以将它保存为长格式的 data.table(即跳过最后一步),在我的机器上大约需要 2 秒。
为了比较,@qjgods 在我的机器上回答的时间:
#user system elapsed
#3.71 2.08 8.81
请注意,使用
apply
(或它的并行版本)转置矩阵。
这是一个聪明的方法:
res <- matrix(mm[order(row(mm), -mm)], nrow = nrow(mm), byrow = TRUE)
也比别人快:
system.time(
res <- matrix(mm[order(row(mm), -mm)], nrow=nrow(mm), byrow=TRUE)
)
user system elapsed
1.910 0.254 2.170