한곳에서 하나의 빅 데이터 프레임으로 변환하려는 데이터 프레임 목록으로 끝나는 코드가 있습니다.
비슷한 질문 이지만 복잡한 것을 시도 하는 이전 질문 에서 몇 가지 조언을 얻었습니다 .
다음은 내가 시작하는 것의 예입니다 (이는 설명을 위해 크게 단순화되었습니다).
listOfDataFrames <- vector(mode = "list", length = 100)
for (i in 1:100) {
listOfDataFrames[[i]] <- data.frame(a=sample(letters, 500, rep=T),
b=rnorm(500), c=rnorm(500))
}
나는 현재 이것을 사용하고있다 :
df <- do.call("rbind", listOfDataFrames)
답변
dplyr 패키지에서 bind_rows ()를 사용하십시오.
bind_rows(list_of_dataframes, .id = "column_label")
답변
다른 옵션은 plyr 함수를 사용하는 것입니다.
df <- ldply(listOfDataFrames, data.frame)
원본보다 약간 느립니다.
> system.time({ df <- do.call("rbind", listOfDataFrames) })
user system elapsed
0.25 0.00 0.25
> system.time({ df2 <- ldply(listOfDataFrames, data.frame) })
user system elapsed
0.30 0.00 0.29
> identical(df, df2)
[1] TRUE
내 생각에 do.call("rbind", ...)
(a) data.frames 대신 행렬을 사용하고 (b) 최종 행렬을 사전 할당하고 그것을 늘리지 않고 할당하는 것과 같은 작업을 수행 할 수 없다면 사용하는 것이 가장 빠른 접근 방법이 될 것입니다. .
편집 1 :
Hadley의 의견을 바탕으로 rbind.fill
CRAN 의 최신 버전은 다음 과 같습니다.
> system.time({ df3 <- rbind.fill(listOfDataFrames) })
user system elapsed
0.24 0.00 0.23
> identical(df, df3)
[1] TRUE
이것은 rbind보다 쉽고, 조금 더 빠릅니다 (이러한 타이밍은 여러 번의 실행을 유지합니다). 그리고 내가 이해하는 한, github 의 버전plyr
은 이것보다 훨씬 빠릅니다.
답변
완전성을 기하기 위해이 질문에 대한 답변을 업데이트해야한다고 생각했습니다. “제 생각에 사용하는 do.call("rbind", ...)
것이 가장 빠른 접근 방법이 될 것입니다 …”아마도 2010 년 5 월과 얼마 후에는 사실 이었지만 2011 년 9 월쯤에 패키지 버전 1.8.2 rbindlist
에 새로운 기능 이 도입되었습니다. data.table
, “와 동일 do.call("rbind",l)
하지만 훨씬 더 빠릅니다”라는 설명이 포함되어 있습니다. 얼마나 빨리?
library(rbenchmark)
benchmark(
do.call = do.call("rbind", listOfDataFrames),
plyr_rbind.fill = plyr::rbind.fill(listOfDataFrames),
plyr_ldply = plyr::ldply(listOfDataFrames, data.frame),
data.table_rbindlist = as.data.frame(data.table::rbindlist(listOfDataFrames)),
replications = 100, order = "relative",
columns=c('test','replications', 'elapsed','relative')
)
test replications elapsed relative
4 data.table_rbindlist 100 0.11 1.000
1 do.call 100 9.39 85.364
2 plyr_rbind.fill 100 12.08 109.818
3 plyr_ldply 100 15.14 137.636
답변
암호:
library(microbenchmark)
dflist <- vector(length=10,mode="list")
for(i in 1:100)
{
dflist[[i]] <- data.frame(a=runif(n=260),b=runif(n=260),
c=rep(LETTERS,10),d=rep(LETTERS,10))
}
mb <- microbenchmark(
plyr::rbind.fill(dflist),
dplyr::bind_rows(dflist),
data.table::rbindlist(dflist),
plyr::ldply(dflist,data.frame),
do.call("rbind",dflist),
times=1000)
ggplot2::autoplot(mb)
세션:
R version 3.3.0 (2016-05-03)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1
> packageVersion("plyr")
[1] ‘1.8.4’
> packageVersion("dplyr")
[1] ‘0.5.0’
> packageVersion("data.table")
[1] ‘1.9.6’
업데이트 : 2018 년 1 월 31 일 다시 실행하십시오. 같은 컴퓨터에서 실행했습니다. 새로운 버전의 패키지. 씨앗 애호가를위한 씨앗을 추가했습니다.
set.seed(21)
library(microbenchmark)
dflist <- vector(length=10,mode="list")
for(i in 1:100)
{
dflist[[i]] <- data.frame(a=runif(n=260),b=runif(n=260),
c=rep(LETTERS,10),d=rep(LETTERS,10))
}
mb <- microbenchmark(
plyr::rbind.fill(dflist),
dplyr::bind_rows(dflist),
data.table::rbindlist(dflist),
plyr::ldply(dflist,data.frame),
do.call("rbind",dflist),
times=1000)
ggplot2::autoplot(mb)+theme_bw()
R version 3.4.0 (2017-04-21)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1
> packageVersion("plyr")
[1] ‘1.8.4’
> packageVersion("dplyr")
[1] ‘0.7.2’
> packageVersion("data.table")
[1] ‘1.10.4’
업데이트 : 2019 년 8 월 6 일 다시 실행하십시오.
set.seed(21)
library(microbenchmark)
dflist <- vector(length=10,mode="list")
for(i in 1:100)
{
dflist[[i]] <- data.frame(a=runif(n=260),b=runif(n=260),
c=rep(LETTERS,10),d=rep(LETTERS,10))
}
mb <- microbenchmark(
plyr::rbind.fill(dflist),
dplyr::bind_rows(dflist),
data.table::rbindlist(dflist),
plyr::ldply(dflist,data.frame),
do.call("rbind",dflist),
purrr::map_df(dflist,dplyr::bind_rows),
times=1000)
ggplot2::autoplot(mb)+theme_bw()
R version 3.6.0 (2019-04-26)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 18.04.2 LTS
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/openblas/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.2.20.so
packageVersion("plyr")
packageVersion("dplyr")
packageVersion("data.table")
packageVersion("purrr")
>> packageVersion("plyr")
[1] ‘1.8.4’
>> packageVersion("dplyr")
[1] ‘0.8.3’
>> packageVersion("data.table")
[1] ‘1.12.2’
>> packageVersion("purrr")
[1] ‘0.3.2’
답변
도 있습니다 bind_rows(x, ...)
에서 dplyr
.
> system.time({ df.Base <- do.call("rbind", listOfDataFrames) })
user system elapsed
0.08 0.00 0.07
>
> system.time({ df.dplyr <- as.data.frame(bind_rows(listOfDataFrames)) })
user system elapsed
0.01 0.00 0.02
>
> identical(df.Base, df.dplyr)
[1] TRUE
답변
여기에 또 다른 방법이 있습니다 ( reduce
루프를 대체하는 것으로 종종 간과되는 매우 효과적인 기능 도구 이기 때문에 답변에 추가하기 만하면 됩니다.이 경우에는이 둘 중 어느 것도 do.call보다 훨씬 빠르지 않습니다).
기본 R을 사용하는 경우 :
df <- Reduce(rbind, listOfDataFrames)
또는 tidyverse를 사용하여 :
library(tidyverse) # or, library(dplyr); library(purrr)
df <- listOfDataFrames %>% reduce(bind_rows)
답변
tidyverse에서 어떻게 수행해야합니까?
df.dplyr.purrr <- listOfDataFrames %>% map_df(bind_rows)