【发布时间】:2015-11-07 15:20:50
【问题描述】:
我有一对非常大的 data.frames df1 和 df2(>500,000 行),行数不同,都包含相同的 4 列(X、Y、Z 坐标和计数属性)。 Doomie 示例:
df1<-data.frame(x=c(3,5,2,4),y=c(8,5,7,6),z=c(13,15,12,10),
count=c(10,20,4,12))
df2<-data.frame(x=c(4,3,6),y=c(6,9,8),z=c(10,13,15),count=c(4,7,3))
我只想为匹配 XYZ 的行(相同的空间点)减去计数列 (df1$count - df2$count)。我找到了一种使用函数merge() {base} 的方法,但它很慢而且df 非常大。
任何提示我怎样才能让它更快???我应该尝试引入并行处理吗?任何提示如何与此类示例并行执行,而无需将 df 切成块?
谢谢。
我的实现:
df3<-merge(df1,df2,by.x=c("x","y", "z"),by.y=c("x","y", "z"),all.x=T,all.y=TRUE)
df3[is.na(df3$count.x),4]<-0
df3[is.na(df3$count.y),5]<-0
df3$countdif<-df3$count.y-df3$count.x
新编辑。 回答: Akrun 的回答中的 2 条建议效果很好。第一个在微基准测试中速度提高了 2 倍,并且也适用于我的大型数据帧。这里是他们的基准:
使用 dplyr {}
dodplyr<- function (a,b){
dfN<- full_join(a,b, by=c('x', 'y', 'z')) %>%
mutate_each(funs(replace(., which(is.na(.)), 0)),
starts_with('count')) %>%
mutate(countdif= count.y-count.x)
dfN<-select(dfN,-count.x,-count.y)
return(dfN)
}
和使用 data.table {}
dodata.table<-function(a,b){
setDT(a)
setDT(b)
DT <- merge(a,b, by=c('x', 'y', 'z'), all=TRUE)
for(j in 4:5){set(DT, i=which(is.na(DT[[j]])), j=j, value=0)}
DT[, countdif:= count.y-count.x]
DT[,c("count.x","count.y"):=NULL]
return(DT)
}
还有微基准:
times <- microbenchmark( dodplyr(df1,df2), dodata.table(df1,df2), times=1e3)
> times
Unit: milliseconds
expr min lq mean median uq max neval
dodplyr(df1, df2) 2.374164 2.489710 2.978814 2.590829 2.704017 18.15356 1000
dodata.table(df1, df2) 5.094271 5.308994 6.458764 5.534259 5.675328 37.23370 1000
但是,我无法将它们与我使用 merge{base} 和 dfs 的实现进行比较。我试图包含它,但在调用微基准测试时出现错误。这是我尝试过的:
domerge<- function(a,b){
dfm<-merge(a,b,by.x=c("x","y", "z"),by.y=c("x","y", "z"),all.x=T,all.y=TRUE)
dfm[is.na(dfm$count.x),4]<-0
dfm[is.na(dfm$count.y),5]<-0
dfm$countdif<-dfm$count.y-dfm$count.x
dfm<-dfm[,c(1:3,6)]
return(dfm)
}
调用它时有效,例如df3<-domerge(df1,df2) 但在进行微基准测试时会出错:
> times <- microbenchmark(domerge(df1,df2), dodplyr(df1,df2), dodata.table(df1,df2), times=1e3)
Show Traceback
Rerun with Debug
Error in merge.data.table(a, b, by.x = c("x", "y", "z"), by.y = c("x", :
Can not match keys in x and y to automatically determine appropriate `by` parameter. Please set `by` value explicitly.
【问题讨论】:
-
merge()在当前的开发版本 1.9.5 中有不少改进。但是对于旨在扩展大数据的工具而言,us/ms 规模的基准相对没有意义,而且您很可能只是测量[.data.table调用的开销。 -
@Arun,非常感谢您的评论。对不起,我的无知,但你的意思是:“我们/毫秒尺度上的基准对于旨在扩展大数据的工具来说相对没有意义”。另一方面,您是否认为这种情况下 data.table 方法的实际性能可能比 dplyr 更快?我怎么知道除了基准测试之外哪个性能更好?谢谢!
标签: r dataframe parallel-processing large-data