Aggregate довольно быстрый, но вы можете использовать более подходящее решение для распараллеливания кода. Это легко сделать в Windows, используя snowfall
:
require(snowfall)
sfInit(parallel=TRUE,cpus=2)
sfExport("Data")
ID <- unique(Data$ID)
CombNames <- sfSapply(ID,function(i){
paste(Data$Names[Data$ID==i],collapse=" | ")
})
data.frame(ID,CombNames)
sfStop()
Параллельная версия даст вам дополнительное ускорение, но единственное решение Sapply на самом деле медленнее, чем агрегат. Tapply немного быстрее, но его нельзя распараллелить, используя снегопад. на моем компьютере:
n <- 3000
m <- 3
Data <- data.frame( ID = rep(1:n,m),
Names=rep(LETTERS[1:m],each=n))
# using snowfall for parallel sapply
system.time({
ID <- unique(Data$ID)
CombNames <- sfSapply(ID,function(i){
paste(Data$Names[Data$ID==i],collapse=" | ")
})
data.frame(ID,CombNames)
})
user system elapsed
0.02 0.00 0.33
# using tapply
system.time({
CombNames <- tapply(Data$Names,Data$ID,paste,collapse=" | ")
data.frame(ID=names(CombNames),CombNames)
})
user system elapsed
0.44 0.00 0.44
# using aggregate
system.time(
aggregate(Names ~ ID, data=Data, FUN=paste, collapse=" | ")
)
user system elapsed
0.47 0.00 0.47
# using the normal sapply
system.time({
ID <- unique(Data$ID)
CombNames <- sapply(ID,function(i){
paste(Data$Names[Data$ID==i],collapse=" | ")
})
data.frame(ID,CombNames)
})
user system elapsed
0.75 0.00 0.75
Примечание:
Для справки, лучшее решение для сапплей было бы:
CombNames <- sapply(split(Data$Names,Data$ID),paste,collapse=" | ")
data.frame(ID=names(CombNames),CombNames)
, что эквивалентно tapply. Но распараллеливание этого на самом деле медленнее, так как вам нужно перемещать больше данных внутри sfSapply
. Скорость зависит от копирования набора данных в каждый процессор. Это то, что вы должны иметь в виду, когда ваш набор данных огромен: вы заплатите за скорость, используя больше памяти.