Crea un data.frame donde una columna es una lista

80

Sé cómo agregar una columna de lista:

> df <- data.frame(a=1:3)
> df$b <- list(1:1, 1:2, 1:3)
> df
  a       b
1 1       1
2 2    1, 2
3 3 1, 2, 3

Esto funciona, pero no:

> df <- data.frame(a=1:3, b=list(1:1, 1:2, 1:3))
Error in data.frame(1L, 1:2, 1:3, check.names = FALSE, stringsAsFactors = TRUE) : 
  arguments imply differing number of rows: 1, 2, 3

¿Por qué?

Además, ¿hay alguna forma de crear df(arriba) en una sola llamada a data.frame?

flodel
fuente

Respuestas:

103

Ligeramente oscuramente, de ?data.frame:

Si una lista, marco de datos o matriz se pasa a 'data.frame' es como si cada componente o columna se hubiera pasado como un argumento separado (excepto para las matrices de clase '"model.matrix"' y las protegidas por 'I ' ).

(énfasis añadido).

Entonces

data.frame(a=1:3,b=I(list(1,1:2,1:3)))

parece funcionar.

Ben Bolker
fuente
17
Para los interesados, "I" significa "Inhibir la interperetación / conversión de objetos". Crea un objeto idéntico pero con "AsIs" adjuntos al conjunto de clases. La clase "AsIs" está realmente ahí para ser leída por las funciones data.frame () y formula (). Obtenga más información aquí .
pwilcox
2
increíble, gracias por la solución. aunque solo Ipara Inhibir Interperetation / Conversión de objetos parece un poco demasiado corto :)
sertsedat
@pwilcox muy interesante. ¿Existe algún método para llamar a un objeto para comprender si está protegido por yo? Creo que es class()? p I(iris) -> i; i %>% class() 3 [1] "AsIs" "data.frame". ej. (devuelve la clase AsIs)
stevec
33

Si está trabajando con data.tables, puede evitar la llamada aI()

library(data.table)
# the following works as intended
data.table(a=1:3,b=list(1,1:2,1:3))

   a     b
1: 1     1
2: 2   1,2
3: 3 1,2,3
mnel
fuente
Esta es una característica subestimada data.tablepor un amplio margen
data princess
22

data_frames (llamados diversamente tibbles, tbl_df, tbl) de forma nativa apoyan la creación de columnas de la lista utilizando el data_frameconstructor. Para usarlos, cargue una de las muchas bibliotecas con ellos, como tibble, dplyro tidyverse.

> data_frame(abc = letters[1:3], lst = list(1:3, 1:3, 1:3))
# A tibble: 3 × 2
    abc       lst
  <chr>    <list>
1     a <int [3]>
2     b <int [3]>
3     c <int [3]>

En realidad, están data.framesbajo el capó, pero algo modificados. Casi siempre se pueden utilizar normalmente data.frames. La única excepción que he encontrado es que cuando las personas hacen controles de clase inapropiados, causan problemas:

> #no problem
> data.frame(x = 1:3, y = 1:3) %>% class
[1] "data.frame"
> data.frame(x = 1:3, y = 1:3) %>% class == "data.frame"
[1] TRUE
> #uh oh
> data_frame(x = 1:3, y = 1:3) %>% class
[1] "tbl_df"     "tbl"        "data.frame"
> data_frame(x = 1:3, y = 1:3) %>% class == "data.frame"
[1] FALSE FALSE  TRUE
> #dont use if with improper testing!
> if(data_frame(x = 1:3, y = 1:3) %>% class == "data.frame") "something"
Warning message:
In if (data_frame(x = 1:3, y = 1:3) %>% class == "data.frame") "something" :
  the condition has length > 1 and only the first element will be used
> #proper
> data_frame(x = 1:3, y = 1:3) %>% inherits("data.frame")
[1] TRUE

Recomiendo leer sobre ellos en R 4 Data Science (gratis).

CoderGuy123
fuente
1
R se está moviendo y creciendo y creo que esta es la respuesta de 2018 a la pregunta y de alguna manera debería estar marcada como tal.
Fitzroy Hogsflesh
Si es lo suficientemente popular, llegará a la cima. Muchos de nosotros todavía usamos la base R ...
Ben Bolker