我的数据框大小约为20,000 x 300,我目前正使用na.aggregate
zoo
来为每列填充最大值。如果组中有所有NA,则应返回NA
。我正在尝试为我的代码块找到一个更有效的解决方案来加快速度。这是一个玩具数据框架,以及dplyr
解决方案的尝试速度比na.aggregate
版本慢约10倍:
library(zoo)
library(dplyr)
library(microbenchmark)
# toy data frame
DF <- tibble(group=c(rep("A",4),rep("B",2),rep("C",3)),
Col1=rep(NA_real_,9),
Col2=c(5,3,2,NA,NA,NA,1,2,NA),
Col3=c(NA,NA,NA,NA,1,NA,2,3,NA))
# na.aggregate solution
na.agg <- function(DF){
agg.max <- suppressWarnings(na.aggregate(DF,DF$group,FUN=max))
agg.max[,2:ncol(agg.max)] <- apply(agg.max[,2:ncol(agg.max)],2,as.numeric)
return(agg.max)
}
# dplyr solution
dplyr.agg <- function(DF){
Sol.2 <- DF %>%
group_by(group) %>%
mutate_all(funs(case_when(
all(is.na(.))~NA_real_,
is.na(.)~max(.,na.rm=TRUE),
TRUE ~ as.numeric(I(.)))))
}
# Timing test
res <- microbenchmark(na.agg(DF),dplyr.agg(DF))
print(res)
Unit: milliseconds
expr min lq mean median uq max neval
na.agg(DF) 1.698281 1.879652 2.122334 2.063809 2.297201 3.763934 100
dplyr.agg(DF) 10.730040 11.553523 12.484254 12.068044 12.778734 21.239836 100
是否有更快的rcpp
,data.table
或更好的dplyr
解决方案?
答案 0 :(得分:1)
还有更快的速度从na.agg
开始。不要在整个na.aggregate
上DF
,因为包含group
列意味着所有内容都会转换为字符,这会减慢速度。在DF[-1]
上运行,不包括group
,您甚至不需要事后进行as.numeric转换。
na.agg2 <- function(DF) {
DF[-1] <- na.aggregate(DF[-1], DF$group, FUN=function(x) if(all(is.na(x))) NA else max(x) )
DF
}
与当前na.agg
:
microbenchmark(na.agg(DF),na.agg2(DF))
#Unit: milliseconds
# expr min lq mean median uq max neval
# na.agg(DF) 2.127476 2.145621 2.232542 2.163216 2.216366 3.433873 100
# na.agg2(DF) 1.047977 1.055675 1.560371 1.062455 1.080783 49.378785 100
使用data.table
似乎再次更快:
DT <- copy(DF)
DT <- as.data.table(DT)
DT[,
lapply(.SD, function(x) if(all(is.na(x))) NA_real_ else
replace(x,is.na(x),max(x,na.rm=TRUE))),
by=group
]