डेटा फ़्रेम की एक सूची को एक डेटा फ़्रेम में कनवर्ट करें


336

मेरे पास कोड है कि एक स्थान पर डेटा फ़्रेम की एक सूची समाप्त होती है, जिसे मैं वास्तव में एक बड़े डेटा फ़्रेम में परिवर्तित करना चाहता हूं।

मुझे पहले वाले प्रश्न से कुछ संकेत मिले जो कुछ इसी तरह के और अधिक जटिल काम करने की कोशिश कर रहा था।

यहाँ एक उदाहरण है जो मैं शुरू कर रहा हूँ (यह चित्रण के लिए सरल है):

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)

इस प्रश्न को भी देखें: stackoverflow.com/questions/2209258/…
शेन

27
do.call("rbind", list)मुहावरा है कि मैं क्या करने से पहले के रूप में अच्छी इस्तेमाल किया है है। आपको प्रारंभिक की आवश्यकता क्यों है unlist?
डिर्क एडल्डबुलेटेल

5
क्या कोई मुझे do.call ("rbind", सूची) और rbind (सूची) के बीच का अंतर समझा सकता है - आउटपुट समान क्यों नहीं हैं?
user6571411

1
@ user6571411 क्योंकि do.call () एक-एक करके तर्कों को वापस नहीं करता है, लेकिन फ़ंक्शन की तर्कों को रखने के लिए एक सूची का उपयोग करता है। देखें https://www.stat.berkeley.edu/~s133/Docall.html
Marjolein Fokkema

जवाबों:


130

Dplyr पैकेज से bind_rows () का उपयोग करें:

bind_rows(list_of_dataframes, .id = "column_label")

5
अच्छा समाधान है। .id = "column_label"सूची तत्व नामों के आधार पर अद्वितीय पंक्ति नाम जोड़ता है।
सिबो जियांग

10
चूंकि यह 2018 है और dplyrउपयोग करने के लिए तेज और एक ठोस उपकरण दोनों है, इसलिए मैंने इसे स्वीकार किए गए उत्तर में बदल दिया है। साल, वे से उड़ना!
जद लॉन्ग

186

एक अन्य विकल्प एक प्लाई समारोह का उपयोग करने के लिए है:

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", ...) करना सबसे तेज़ तरीका है जो आपको तब तक मिलेगा जब तक आप कुछ नहीं कर सकते हैं जैसे (क) डेटा के बजाय मैट्रिसेस का उपयोग करें। और (बी) अंतिम मैट्रिक्स का प्रचार करें और इसे बढ़ने के बजाय इसे असाइन करें ।

1 संपादित करें :

हेडली की टिप्पणी के आधार पर, यहाँ rbind.fillCRAN का नवीनतम संस्करण है :

> system.time({ df3 <- rbind.fill(listOfDataFrames) })
   user  system elapsed 
   0.24    0.00    0.23 
> identical(df, df3)
[1] TRUE

यह rbind की तुलना में आसान है, और थोड़ी तेजी से (ये समय कई रनों से अधिक है)। और जहां तक ​​मैं इसे समझता हूं, गीथब का संस्करणplyr इससे भी तेज है।


28
plyr के नवीनतम संस्करण में rbind.fill do.call और rbind की तुलना में काफी तेज है
हैडली

1
दिलचस्प। मेरे लिए rbind.fill सबसे तेज था। अजीब पर्याप्त, do.call / rbind ने समान TRUE नहीं लौटाया, भले ही मैं अंतर पा सकता था। अन्य दो बराबर थे लेकिन प्लाई धीमी थी।
बजे मैट बैनर्ट

I()data.frameआपकी ldplyकॉल
बैपटिस्ट

4
वहाँ भी melt.listreshape (2) में है
बपतिस्मा देनेवाला

do.call(function(...) rbind(..., make.row.names=F), df)उपयोगी है यदि आप स्वचालित रूप से जनरेट किए गए अनूठे रोनामे नहीं चाहते हैं।
smci

111

संपूर्णता के उद्देश्य से, मैंने सोचा कि इस प्रश्न के उत्तर के लिए एक अद्यतन की आवश्यकता है। "मेरा अनुमान है कि उपयोग do.call("rbind", ...)करना सबसे तेज़ तरीका है जो आप पाएंगे ..." यह मई 2010 के लिए और कुछ समय बाद शायद सही था, लेकिन सितंबर 2011 के बारे 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

3
इसके लिए आपको बहुत धन्यवाद - मैं अपने बालों को बाहर निकाल रहा था क्योंकि मेरे डेटा सेट ldplyलंबे, पिघले हुए डेटा फ़्रेमों के झुंड के लिए बहुत बड़े हो रहे थे । वैसे भी, मुझे आपके rbindlistसुझाव का उपयोग करके एक अविश्वसनीय गति प्राप्त हुई ।
KarateSnowMachine 5

11
और पूर्णता के लिए एक और: dplyr::rbind_all(listOfDataFrames)चाल भी करेगा।
एंडीचर

2
वहाँ एक बराबर है, rbindlistलेकिन स्तंभ द्वारा डेटा फ्रेम संलग्न? एक cbindlist की तरह कुछ?
राफा.पेरेरा

2
@ rafa.pereira हाल ही में एक सुविधा अनुरोध है: फ़ंक्शन cbindlist जोड़ें
हेनरिक

मैं अपने बालों को भी बाहर खींच रहा था क्योंकि do.call()18 घंटे से डेटा फ़्रेम की सूची में चल रहा था, और अभी भी समाप्त नहीं हुआ था, धन्यवाद !!!
ग्रीम फ्रॉस्ट

74

बाँध-साजिश

कोड:

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

UPDATE : Rerun 31-Jan-2018 उसी कंप्यूटर पर भाग गया। पैकेज के नए संस्करण। बीज प्रेमियों के लिए जोड़ा बीज।

यहां छवि विवरण दर्ज करें

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

अद्यतन : Rerun 06-Aug-2019।

यहां छवि विवरण दर्ज करें

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

2
यह एक बेहतरीन जवाब है। मैंने एक ही चीज़ (एक ही OS, एक ही पैकेज, अलग-अलग रैंडमाइजेशन क्योंकि आप नहीं चलाते हैं set.seed) पर सबसे खराब स्थिति वाले प्रदर्शन में कुछ अंतर देखा। rbindlistवास्तव में मेरे परिणाम में सबसे खराब-केस के साथ-साथ सबसे अच्छा ठेठ-केस भी था
C8H10N4O2

48

में भी 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

तकनीकी रूप से बोलने के लिए आपको as.data.frame की आवश्यकता नहीं है - यह सब करता है यह विशेष रूप से एक data.frame बनाता है, जैसा कि एक table_df (deplyr से) के
विपरीत

14

यहाँ एक और तरीका यह किया जा सकता है (सिर्फ इसलिए इसे उत्तरों में जोड़ दिया गया है reduce एक बहुत प्रभावी कार्यात्मक उपकरण है जिसे अक्सर छोरों के प्रतिस्थापन के रूप में अनदेखा किया जाता है। इस विशेष मामले में, इनमें से कोई भी do.call की तुलना में काफी तेज नहीं है)

आधार R का उपयोग करना:

df <- Reduce(rbind, listOfDataFrames)

या, tidyverse का उपयोग कर:

library(tidyverse) # or, library(dplyr); library(purrr)
df <- listOfDataFrames %>% reduce(bind_rows)

11

यह कैसे tidyverse में किया जाना चाहिए:

df.dplyr.purrr <- listOfDataFrames %>% map_df(bind_rows)

3
mapयदि आप bind_rowsडेटाफ्रेम की सूची ले सकते हैं तो आप इसका उपयोग क्यों करेंगे ?
देखें

9

हाल के कुछ उत्तरों की तुलना करने के इच्छुक लोगों के लिए एक अद्यतन दृश्य (मैं purrr से 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

7

केवल एक चीज जो data.tableगायब है, वह पहचानकर्ता कॉलम है जिससे यह जाना जा सकता है कि डेटा की सूची में से डेटाफ्रेम कहां से आ रहा है।

कुछ इस तरह:

df_id <- data.table::rbindlist(listOfDataFrames, idcol = TRUE)

idcolपैरामीटर एक स्तंभ (कहते हैं .id) dataframe सूची में निहित के मूल की पहचान। परिणाम कुछ इस तरह दिखेगा:

.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  
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.