데이터 프레임 목록을 한 행씩 하나의 데이터 프레임으로 결합
하나의 빅 데이터 프레임으로 변환하고 싶은 데이터 프레임의 리스트가 되는 코드가 있습니다.
나는 비슷하지만 더 복잡한 무언가를 하려고 하는 이전 질문에서 몇 가지 힌트를 얻었다.
다음으로 예를 제시하겠습니다(이것은 일러스트레이션용으로 대폭 간략화되어 있습니다).
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)
사용하다bind_rows()
dplyr 패키지:
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) 데이터 대신 매트릭스를 사용하고 (b) 최종 매트릭스를 미리 할당하여 할당하지 않고 할당하지 않는 한 가장 빠른 접근법이 됩니다.
편집 1:
해들리의 코멘트를 바탕으로, 여기 최신 버전이 있습니다.rbind.fill
CRAN에서:
> system.time({ df3 <- rbind.fill(listOfDataFrames) })
user system elapsed
0.24 0.00 0.23
> identical(df, df3)
[1] TRUE
이는 rbind보다 쉽고 약간 더 빠릅니다(이러한 타이밍은 여러 번의 실행에 걸쳐 유지됨).그리고 제가 알기론 on github 버전은 이보다 더 빠릅니다.
완성도를 높이기 위해 이 질문에 대한 답변은 업데이트가 필요하다고 생각했습니다."내 추측으로는do.call("rbind", ...)
아마 2010년 5월에도 그랬을 것이고, 그 후 얼마 지나지 않아 2011년 9월에 새로운 기능이 등장했습니다.rbindlist
에 도입되었습니다.data.table
패키지 버전 1.8.2에는 다음과 같은 설명이 붙어 있습니다.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’
업데이트: 2021년 11월 18일 재실행.
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),
Reduce("rbind",dflist),
purrr::map_df(dflist,dplyr::bind_rows),
times=1000)
ggplot2::autoplot(mb)+theme_bw()
R version 4.1.2 (2021-11-01)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19043)
>packageVersion("plyr")
[1] ‘1.8.6’
> packageVersion("dplyr")
[1] ‘1.0.7’
> packageVersion("data.table")
[1] ‘1.14.2’
> packageVersion("purrr")
[1] ‘0.3.4’
또 있다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)
깔끔하게 하는 방법:
df.dplyr.purrr <- listOfDataFrames %>% map_df(bind_rows)
솔루션이 가지고 있는 유일한 것은data.table
are missing은 데이터가 목록 내의 어느 데이터 프레임에서 왔는지 알기 위한 식별자 컬럼입니다.
다음과 같은 경우:
df_id <- data.table::rbindlist(listOfDataFrames, idcol = TRUE)
idcol
합니다(파라미터)..id
을 사용하다
.id a b c
1 u -0.05315128 -1.31975849
1 b -1.00404849 1.15257952
1 y 1.17478229 -0.91043925
1 q -1.65488899 0.05846295
1 c -1.43730524 0.95245909
1 b 0.56434313 0.93813197
최근 답변의 일부를 비교하고 싶은 사용자를 위한 최신 비주얼(purr과 dplyr 솔루션을 비교하고 싶었다).기본적으로는 @TheVTM과 @rmf의 답변을 조합했습니다.
코드:
library(microbenchmark)
library(data.table)
library(tidyverse)
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(
dplyr::bind_rows(dflist),
data.table::rbindlist(dflist),
purrr::map_df(dflist, bind_rows),
do.call("rbind",dflist),
times=500)
ggplot2::autoplot(mb)
세션 정보:
sessionInfo()
R version 3.4.1 (2017-06-30)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1
패키지 버전:
> packageVersion("tidyverse")
[1] ‘1.1.1’
> packageVersion("data.table")
[1] ‘1.10.0’
★★purrr 1.0.0
는 , 입니다.list_rbind
:
library(purrr)
list_rbind(listOfDataFrames, names_to = "column_label")
언급URL : https://stackoverflow.com/questions/2851327/combine-a-list-of-data-frames-into-one-data-frame-by-row
'source' 카테고리의 다른 글
Excel 시트에 PostgreSQL 쿼리 (0) | 2023.04.29 |
---|---|
자동 트리거 없이 zure 웹 작업을 연속적으로 실행하고 public static 함수를 호출하는 방법 (0) | 2023.04.29 |
작업 이름 "..getProjectMetadata"가 없습니다. (0) | 2023.04.24 |
정규식으로 파일 형식 검증 (0) | 2023.04.24 |
지시문 @Input 필요 (0) | 2023.04.24 |