web-dev-qa-db-fra.com

Créer un data.frame où une colonne est une liste

Je sais comment ajouter une colonne de liste:

> 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

Cela fonctionne, mais pas:

> 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

Pourquoi?

Est-il également possible de créer df (ci-dessus) en un seul appel à data.frame?

65
flodel

Légèrement obscur, de ?data.frame:

Si une liste ou un bloc de données ou une matrice est passé à 'data.frame', c'est comme si chaque composant ou colonne avait été passé comme un argument séparé (sauf pour les matrices de la classe '"model.matrix"' et celles protégées par 'I ').

Alors

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

semble fonctionner.

84
Ben Bolker

Si vous travaillez avec data.tables, Vous pouvez éviter l'appel à I()

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
30
mnel

data_frames (diversement appelé tibbles, tbl_df, tbl) prennent en charge de manière native la création de colonnes de liste à l'aide de data_frame constructeur. Pour les utiliser, chargez avec elles l'une des nombreuses bibliothèques telles que tibble , dplyr ou 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]>

Ils sont en fait data.frames sous le capot, mais quelque peu modifié. Ils peuvent presque toujours être utilisés normalement data.frames. La seule exception que j'ai trouvée est que lorsque les gens font des vérifications de classe inappropriées, ils causent des problèmes:

> #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

Je recommande de lire à leur sujet dans R 4 Data Science (gratuit).

18
Deleet