我希望根据列总结数据框中的一些变量。然而,我的数据框架相当大(> 30,000,000行),并且在dplyr中使用汇总函数需要很长时间才能运行。 R中有更快的方法来加速汇总过程吗?
我的格式为数据框df:
proid X1 X2 X3 X4
1 1 zz a e a
2 2 ff g z b
3 1 cd s f d
4 3 ab t e e
5 2 ta b h k
....
当它们具有相同的prodid值时,我希望将变量X1连接到X4。连接的字符串用逗号分隔。所以上表应该给我新表:
proid X1 X2 X3 X4
1 1 zz,cd a,s e,f a,d
2 2 ff,ta g,b z,h b,k
3 3 ab t e e
....
我使用了以下dplyr代码:
concat <- function(x){
x <- na.omit(x)
if(length(x)==0){
return(as.character(NA))
}else{
return(paste(x,collapse=","))
}
}
dg<-group_by(df,proid)
df<-summarise(dg,proid,concat(X1),concat(X2),concat(X3),concat(X4))
答案 0 :(得分:11)
编辑注释删除了我的答案的原始部分,但没有解决NA处理问题。增加了基准。
concat2 <- function(x) if(all(is.na(x))) NA_character_ else paste(na.omit(x), collapse = ",")
使用data.table:
setDT(df)[, lapply(.SD, concat2), by = proid, .SDcols = -c("X4")]
# proid X1 X2 X3
#1: 1 zz,cd a,s e,f
#2: 2 ff,ta g,b z,h
#3: 3 NA t e
使用dplyr:
df %>% group_by(proid) %>% summarise_each(funs(concat2), -X4)
基准,数据比实际使用情况要小,而且没有完全代表性,所以只想了解concat2
与concat
等的对比情况。
library(microbenchmark)
library(dplyr)
library(data.table)
N <- 1e6
x <- c(letters, LETTERS)
df <- data.frame(
proid = sample(1e4, N, TRUE),
X1 = sample(sample(c(x, NA), N, TRUE)),
X2 = sample(sample(c(x, NA), N, TRUE)),
X3 = sample(sample(c(x, NA), N, TRUE)),
X4 = sample(sample(c(x, NA), N, TRUE))
)
dt <- as.data.table(df)
concat <- function(x){
x <- na.omit(x)
if(length(x)==0){
return(as.character(NA))
}else{
return(paste(x,collapse=","))
}
}
concat2 <- function(x) if(all(is.na(x))) NA_character_ else paste(na.omit(x), collapse = ",")
concat.dplyr <- function(){
df %>% group_by(proid) %>% summarise_each(funs(concat), -X4)
}
concat2.dplyr <- function(){
df %>% group_by(proid) %>% summarise_each(funs(concat2), -X4)
}
concat.data.table <- function(){
dt[, lapply(.SD, concat), by = proid, .SDcols = -c("X4")]
}
concat2.data.table <- function(){
dt[, lapply(.SD, concat2), by = proid, .SDcols = -c("X4")]
}
microbenchmark(concat.dplyr(),
concat2.dplyr(),
concat.data.table(),
concat2.data.table(),
unit = "relative",
times = 10L)
Unit: relative
expr min lq median uq max neval
concat.dplyr() 1.058839 1.058342 1.083728 1.105907 1.080883 10
concat2.dplyr() 1.057991 1.065566 1.109099 1.145657 1.079201 10
concat.data.table() 1.024101 1.018443 1.093604 1.085254 1.066560 10
concat2.data.table() 1.000000 1.000000 1.000000 1.000000 1.000000 10
调查结果:data.table在样本数据上的执行速度比dplyr快一点,而concat2
比concat
快一点。但是,此样本数据集的差异仍然很小。
答案 1 :(得分:2)
na.omit
会进行大量不必要的检查和操作。用简单的is.na
调用替换它会给你一个不错的加速:
concat3 = function(x) {
x = x[!is.na(x)]
if (length(x) == 0)
NA_character_
else
paste(x, collapse = ",")
}
使用docendo的数据(但使用字符串而不是因素 - 因素会减慢所有版本的速度):
microbenchmark(dt[, lapply(.SD, concat3), by = proid, .SDcols = -c("X4")],
dt[, lapply(.SD, concat2), by = proid, .SDcols = -c("X4")],
times = 5)
#Unit: milliseconds
# expr min lq mean median uq max neval
# dt[, lapply(.SD, concat3), by = proid, .SDcols = -c("X4")] 960.2475 1079.177 1251.545 1342.684 1402.571 1473.045 5
# dt[, lapply(.SD, concat2), by = proid, .SDcols = -c("X4")] 1718.8121 1892.696 2159.148 2171.772 2470.205 2542.253 5