list - قم بتحويل قائمة من إطارات البيانات إلى إطار بيانات واحد




r dataframe (6)

استخدم bind_rows () من حزمة dplyr:

bind_rows(list_of_dataframes, .id = "column_label")

لدي رمز ينتهي في مكان واحد بقائمة بإطارات البيانات التي أريد تحويلها إلى إطار بيانات كبير واحد.

لدي بعض المؤشرات من سؤال سابق كان يحاول القيام بشيء مماثل ولكنه أكثر تعقيدًا.

في ما يلي مثال على ما أبدأ به (يتم تبسيط ذلك بشكل كبير للتوضيح):

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)

الشيء الوحيد الذي data.table الحلول مع data.table هو عمود المعرّف المراد معرفة من أي مخطط بيانات في القائمة التي تأتي منها البيانات.

شيء من هذا القبيل:

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  

خيار واحد آخر هو استخدام وظيفة 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", ...) سيكون أسرع نهج ستجده إلا إذا كنت تستطيع فعل شيء مثل (أ) استخدام المصفوفات بدلاً من 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 ، وأسرع بشكل هامشي (هذه التوقيتات تصمد فوق تشغيلات متعددة). وبقدر ما أفهمها ، فإن الإصدار من plyr على جيثب أسرع من ذلك.


كيف ينبغي القيام به في الطرف الآخر:

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

هناك أيضا 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)

أو باستخدام طريقة العرض:

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




dataframe