which - working with dataframes in r




R-lista para o frame de dados (12)

Às vezes, seus dados podem ser uma lista de listas de vetores do mesmo tamanho.

lolov = list(list(c(1,2,3),c(4,5,6)), list(c(7,8,9),c(10,11,12),c(13,14,15)) )

(Os vetores internos também podem ser listas, mas estou simplificando para facilitar a leitura).

Então você pode fazer a seguinte modificação. Lembre-se de que você pode anular um nível por vez:

lov = unlist(lolov, recursive = FALSE )
> lov
[[1]]
[1] 1 2 3

[[2]]
[1] 4 5 6

[[3]]
[1] 7 8 9

[[4]]
[1] 10 11 12

[[5]]
[1] 13 14 15

Agora use o seu método favorito mencionado nas outras respostas:

library(plyr)
>ldply(lov)
  V1 V2 V3
1  1  2  3
2  4  5  6
3  7  8  9
4 10 11 12
5 13 14 15

Eu tenho uma lista aninhada de dados. Seu comprimento é 132 e cada item é uma lista de comprimento 20. Existe uma maneira rápida de converter essa estrutura em um quadro de dados que tenha 132 linhas e 20 colunas de dados?

Aqui estão alguns dados de amostra para trabalhar com:

l <- replicate(
  132,
  list(sample(letters, 20)),
  simplify = FALSE
)

Com rbind

do.call(rbind.data.frame, your_list)

Edit: Versão anterior retorna data.frame da list em vez de vetores (como @IanSudbery apontou nos comentários).


Este método usa um pacote tidyverse ( purrr ).

A lista:

x <- as.list(mtcars)

Convertendo-o em um quadro de dados (um tibble mais especificamente):

library(purrr)
map_df(x, ~.x)

Estendendo a resposta de @ Marek: se você quiser evitar que as strings sejam transformadas em fatores e a eficiência não seja uma preocupação, tente

do.call(rbind, lapply(your_list, data.frame, stringsAsFactors=FALSE))

Mais respostas, juntamente com intervalos na resposta a esta pergunta: Qual é a maneira mais eficiente de lançar uma lista como um quadro de dados?

A maneira mais rápida, que não produz um dataframe com listas em vez de vetores para colunas, parece ser (da resposta de Martin Morgan):

l <- list(list(col1="a",col2=1),list(col1="b",col2=2))
f = function(x) function(i) unlist(lapply(x, `[[`, i), use.names=FALSE)
as.data.frame(Map(f(l), names(l[[1]])))

O pacote data.table tem a função rbindlist que é uma implementação super rápida do do.call(rbind, list(...)) .

Pode levar uma lista de lists , data.frames ou data.tables como entrada.

library(data.table)
ll <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3)
  , b = list(var.1 = 4, var.2 = 5, var.3 = 6)
  , c = list(var.1 = 7, var.2 = 8, var.3 = 9)
  , d = list(var.1 = 10, var.2 = 11, var.3 = 12)
  )

DT <- rbindlist(ll)

Isso retorna um data.table herda de data.frame .

Se você realmente quiser converter de volta para um uso as.data.frame(DT)


Para o caso geral de listas profundamente aninhadas com 3 ou mais níveis, como os obtidos de um JSON aninhado:

{
"2015": {
  "spain": {"population": 43, "GNP": 9},
  "sweden": {"population": 7, "GNP": 6}},
"2016": {
  "spain": {"population": 45, "GNP": 10},
  "sweden": {"population": 9, "GNP": 8}}
}

considere a abordagem de melt() para converter a lista aninhada para um formato alto primeiro:

myjson <- jsonlite:fromJSON(file("test.json"))
tall <- reshape2::melt(myjson)[, c("L1", "L2", "L3", "value")]
    L1     L2         L3 value
1 2015  spain population    43
2 2015  spain        GNP     9
3 2015 sweden population     7
4 2015 sweden        GNP     6
5 2016  spain population    45
6 2016  spain        GNP    10
7 2016 sweden population     9
8 2016 sweden        GNP     8

seguido por dcast() então novamente para um conjunto de dados arrumado, onde cada variável forma uma coluna e cada observação forma uma linha:

wide <- reshape2::dcast(tall, L1+L2~L3) 
# left side of the formula defines the rows/observations and the 
# right side defines the variables/measurements
    L1     L2 GNP population
1 2015  spain   9         43
2 2015 sweden   6          7
3 2016  spain  10         45
4 2016 sweden   8          9

Reshape2 produz a mesma saída que o exemplo plyr acima:

library(reshape2)
l <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3)
          , b = list(var.1 = 4, var.2 = 5, var.3 = 6)
          , c = list(var.1 = 7, var.2 = 8, var.3 = 9)
          , d = list(var.1 = 10, var.2 = 11, var.3 = 12)
)
l <- melt(l)
dcast(l, L1 ~ L2)

rendimentos:

  L1 var.1 var.2 var.3
1  a     1     2     3
2  b     4     5     6
3  c     7     8     9
4  d    10    11    12

Se você estivesse quase fora de pixels, você poderia fazer isso tudo em uma linha com reformulação ().


Um modo curto (mas talvez não o mais rápido) de fazer isso seria usar a base r, já que um quadro de dados é apenas uma lista de vetores de tamanho igual . Assim, a conversão entre sua lista de entrada e um data.frame de 30 x 132 seria: df <- data.frame(l) De lá, podemos transpor para uma matriz de 132 x 30 e convertê-la de volta em um dataframe:

new_df <- data.frame(t(df))

Como one-liner: new_df <- data.frame(t(data.frame(l)))

Os nomes de rowns serão muito irritantes de se olhar, mas você pode sempre renomear aqueles com

rownames(new_df) <- 1:nrow(new_df)


Você pode usar o pacote plyr . Por exemplo, uma lista aninhada do formulário

l <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3)
      , b = list(var.1 = 4, var.2 = 5, var.3 = 6)
      , c = list(var.1 = 7, var.2 = 8, var.3 = 9)
      , d = list(var.1 = 10, var.2 = 11, var.3 = 12)
      )

tem agora um comprimento de 4 e cada lista em l contém outra lista do comprimento 3. Agora você pode executar

  library (plyr)
  df <- ldply (l, data.frame)

e deve obter o mesmo resultado que na resposta @Marek e @nico.


data.frame(t(sapply(mylistlist,c)))

sapply converte para uma matriz. data.frame converte a matriz em um quadro de dados.


l <- replicate(10,list(sample(letters, 20)))
a <-lapply(l[1:10],data.frame)
do.call("cbind", a)




dataframe