sapply 版本。它可能存在更优雅的编写方式,但如果您有如您所说的大表,您可以轻松地将其并行化。
使用@denis 提出的数据:
df1 <- data.frame(ID = c("A","B","C"))
df2 <- read.table(text = "
ID Color Type Price
A Green 1 5
A Blue 2 6
A Blue 2 4
B Green 3 7
B Blue 2 2
C Green 2 4
C Blue 4 5
D Green 2 2
D Blue 4 8
",header = T)
这里有一个简单的函数,可以用sapply 做你想做的事:
getPrices <- function(tableid=df1,tablevalues=df2,color="Blue",type=2){
filteredtablevalues <- droplevels(tablevalues[ tablevalues$Color == "Blue" & tablevalues$Type == 2 & tablevalues$ID %in% df1$ID,])
#droplevels could be skipped by using unique(as.character(filteredtablevalues$ID)) in the sapply, not sure what would be the quickest
sapply(levels(filteredtablevalues$ID),function(id,tabval)
{
sum(tabval$Price[tabval$ID == id])
},tabval=filteredtablevalues)
}
如您所见,我添加了两个参数,允许您选择配对颜色/类型。你可以添加这个:
tmp=getPrices(df1,df2)
finaltable=cbind.data.frame(ID=names(tmp),Price=tmp)
如果您绝对需要具有列 ID 和列价格的数据框。
如果我有时间,我会尝试一些基准测试,但是这样编写您应该能够轻松地将其与 library(parallel) 和 library(Rmpi) 并行化,如果您有非常非常大的数据集,这可以挽救您的生命。
编辑:
基准测试:
我无法重现@denis 提出的 dplyr 示例,但我可以比较 data.table 版本:
#Create a bigger dataset
nt=10000 #nt as big as you want
df2=rbind.data.frame(df2,
list(ID= sample(c("A","B","C"),nt,replace=T),
Color=sample(c("Blue","Green"),nt,replace=T),
Type=sample.int(5,nt,replace=T),
Price=sample.int(5,nt,replace=T)
)
)
您可以使用library(microbenchmark) 进行基准测试:
library(microbenchmark)
microbenchmark(sply=getPrices(df1,df2),dtbl=setDT(df2)[ID %in% unique(df1$ID), .(sum = sum(Price[ Type == 2 & Color == "Blue"])),by = ID],dplyr=df2 %>% filter(ID %in% unique(df1$ID)) %>% group_by(ID) %>% summarize(sum = sum(Price[Type==2 & Color=="Blue"])))
在我的电脑上它给出:
Unit: milliseconds
expr min lq mean median uq max neval
sply 78.37484 83.89856 97.75373 89.17033 118.96890 131.3226 100
dtbl 75.67642 83.44380 93.16893 85.65810 91.98584 137.2851 100
dplyr 90.67084 97.58653 114.24094 102.60008 136.34742 150.6235 100
编辑2:
sapply 似乎比data.table 方法稍微快一些,但并不明显。但是使用sapply 可能对您拥有巨大的ID 表非常有帮助。然后您使用library(parallel) 并获得更多时间。
现在data.table 方法似乎是最快的。但是,sapply 的优势在于您可以轻松地将其并行化。虽然在那种情况下,考虑到我是如何编写函数getPrices 的,但只有当你的ID 表很大时它才会有效。