list - índice - numerar figuras automaticamente word 2010




Converter uma lista de quadros de dados em um quadro de dados (6)

A única coisa que faltam nas soluções com data.table é a coluna do identificador para saber de qual dataframe na lista os dados estão vindo.

Algo assim:

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

O parâmetro idcol inclui uma coluna ( .id ) identificando a origem do dataframe contido na lista. O resultado seria algo como isto:

.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  

Eu tenho código que em um lugar acaba com uma lista de quadros de dados que eu realmente quero converter em um único quadro grande de dados.

Eu tenho algumas dicas de uma pergunta anterior que estava tentando fazer algo semelhante, mas mais complexo.

Aqui está um exemplo do que estou começando (isto é simplificado para ilustração):

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))
}

Atualmente estou usando isso:

  df <- do.call("rbind", listOfDataFrames)

Aqui está outra maneira de fazer isso (apenas adicionando-o às respostas, porque reduce é uma ferramenta funcional muito eficaz que é frequentemente ignorada como substituta de loops. Neste caso em particular, nenhum deles é significativamente mais rápido que o do.call).

usando base R:

df <- Reduce(rbind, listOfDataFrames)

ou, usando o tidyverse:

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

Há também bind_rows(x, ...) em 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

Para o propósito de completude, achei que as respostas para essa pergunta exigiam uma atualização. "Meu palpite é que usando do.call("rbind", ...) vai ser a abordagem mais rápida que você vai encontrar ..." Provavelmente foi verdade para maio de 2010 e algum tempo depois, mas em cerca de setembro de 2011 uma nova função rbindlist foi introduzida no pacote data.table versão 1.8.2, com uma observação que "Isto faz o mesmo que do.call("rbind",l) , mas muito mais rápido". Quão rápido?

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

Uma outra opção é usar uma função plyr:

df <- ldply(listOfDataFrames, data.frame)

Isso é um pouco mais lento que o original:

> 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

Meu palpite é que usar do.call("rbind", ...) será a abordagem mais rápida que você encontrará, a menos que você possa fazer algo como (a) usar uma matriz ao invés de um data.frames e (b) pré-aloque a matriz final e atribua a ela em vez de aumentá-la.

Editar 1 :

Com base no comentário de Hadley, aqui está a versão mais recente do rbind.fill do CRAN:

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

Isso é mais fácil que o rbind e marginalmente mais rápido (esses intervalos se mantêm em várias execuções). E até onde eu entendi, a versão do plyr no github é ainda mais rápida que isso.


Use bind_rows () do pacote dplyr:

bind_rows(list_of_dataframes, .id = "column_label")




dataframe