102 votes

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 ?

En outre, existe-t-il un moyen de créer df (ci-dessus) en un seul appel à data.frame ?

130voto

Ben Bolker Points 50041

De façon un peu obscure, de ?data.frame :

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

(accentuation ajoutée).

Alors

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

semble fonctionner.

41voto

mnel Points 48160

Si vous travaillez avec data.tables alors 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

27voto

Deleet Points 2628

data_frame (diversement appelés tibbles , tbl_df , tbl ) prennent nativement en charge la création de colonnes de liste à l'aide de l'élément data_frame Constructeur. Pour les utiliser, chargez l'une des nombreuses bibliothèques qui les contiennent, telles que tibble , dplyr o 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 contrôles de classe inappropriés, 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 vous recommande de les lire dans R 4 Data Science (gratuit).

7voto

GKi Points 6744

Vous pouvez utiliser list2DF a créer un data.frame où une colonne est un list .

x <- list2DF(list(a=1:3, b=list(1:1, 1:2, 1:3)))
#x <- data.frame(a=1:3, list2DF(list(b=list(1:1, 1:2, 1:3)))) #Alternative

x
#  a       b
#1 1       1
#2 2    1, 2
#3 3 1, 2, 3

str(x)
#'data.frame':   3 obs. of  2 variables:
# $ a: int  1 2 3
# $ b:List of 3
#  ..$ : int 1
#  ..$ : int  1 2
#  ..$ : int  1 2 3

Avec cela, vous n'avez pas le attr AsIs dans le data.frame ce que vous auriez en utilisant I .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X