當我想到笨重的時候,就會想到像舊自行車或舊車這樣的東西,而且還會通過遍歷行來處理R中的事情。所以下面的結果看起來比你在問題中發表的內容更加笨拙,但是它依賴於我認爲是更加矢量化的解決方案。以下內容似乎比您上面張貼的時尚代碼快10倍(並返回相同的結果)。
這一建議依賴於reshape2
包:
library(data.table)
library(reshape2)
我已經添加了 「C」 作爲一種可能的column_choice
,使事情變得更有趣一些:
dat=data.table(a_data = c(55,56,57,65),
b_data = c(1,2,3,4),c_data=c(1000,1001,1002,1003),
column_choice = c("a", "c", "a", "b"))
下面是步驟,包裹在一個函數中,以準備它們進行基準測試。
myFun<-function(myDat){
# convert data.table to data.frame for melt()ing
dat1<-data.frame(myDat)
# add ID variable to keep track of things
dat1$ID<-seq_len(nrow(dat1))
# melt data - because of this line, it's important to only
# pass those variables that are used to select the appropriate value
# i.e., a_data,b_data,c_data,column_choice
dat2<-melt(dat1,id.vars=c("ID","column_choice"))
# Determine which value to choose: a, b, or c
dat2$chosen<-as.numeric(dat2$column_choice==substr(dat2$variable,
1,1))*dat2$value
# cast the data back into the original form
dat_cast<-dcast(dat2,ID+column_choice~.,
fun.aggregate=sum,value.var="chosen")
# rename the last variable
names(dat_cast)[ncol(dat_cast)]<-"chosen"
# merge data back together and return results as a data.table
datOUT<-merge(dat1,dat_cast,by=c("ID","column_choice"),sort=FALSE)
return(data.table(datOUT[,c(names(myDat),"chosen")]))
}
這裏是您的解決方案打包成一個功能:
petesFun<-function(myDat){
datOUT=myDat[, data.table(.SD,
chosen=.SD[[paste0(.SD$column_choice, "_data")]]),
by=1:nrow(myDat)]
datOUT$nrow = NULL
return(datOUT)
}
這看起來比myFun
更優雅。基準測試結果顯示出很大的差異,但是:
製作更大的數據。表:
test.df<-data.frame(lapply(dat,rep,100))
test.dat<-data.table(test.df)
和基準:
library(rbenchmark)
benchmark(myRes<-myFun(test.dat),petesRes<-petesFun(test.dat),
replications=25,columns=c("test", "replications", "elapsed", "relative"))
# test replications elapsed relative
# 1 myRes <- myFun(test.dat) 25 0.412 1.00000
# 2 petesRes <- petesFun(test.dat) 25 5.429 13.17718
identical(myRes,petesRes)
# [1] TRUE
我建議「笨重」,可以以不同的方式:)
Doh!非常適合按column_choice +1進行分組。必須有一種方法來避免'cbind()'並且進一步減少時間。用於':='按組的大測試用例,實施時。 – 2012-04-18 13:06:16
使用':='按組編輯好的編輯。理想情況下,我們希望避免使用'.SD'來提高效率(以保存爲每個組所不需要的所有列填充'.SD')。也許:'myDat [,選擇:= myDat [[paste0(column_choice,「_ data」)]] [。I],by = column_choice]'。如果這樣做的話,它應該快得多,因爲'myDat'的列數增長了。 – 2013-03-27 14:10:32