Erstellen Sie einen data.frame, in dem eine Spalte eine Liste ist

80

Ich weiß, wie man eine Listenspalte hinzufügt:

> 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

Das funktioniert, aber nicht:

> 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

Warum?

Gibt es auch eine Möglichkeit, df(oben) in einem einzigen Aufruf von zu erstellen data.frame?

flodel
quelle

Antworten:

103

Etwas dunkel, von ?data.frame:

Wenn eine Liste, ein Datenrahmen oder eine Matrix an 'data.frame' übergeben wird, ist es so, als ob jede Komponente oder Spalte als separates Argument übergeben worden wäre (mit Ausnahme der Matrizen der Klasse "model.matrix" und der durch "I " geschützten ' ).

(Betonung hinzugefügt).

Damit

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

scheint zu funktionieren.

Ben Bolker
quelle
17
Für Interessierte bedeutet "I" "Interperetation / Konvertierung von Objekten verhindern". Es wird ein identisches Objekt erstellt, wobei jedoch "AsIs" an die Klassen angehängt werden. Die Klasse "AsIs" ist wirklich nur dazu da, von den Funktionen data.frame () und formula () gelesen zu werden. Erfahren Sie hier mehr .
Pwilcox
2
super, danke für die lösung. obwohl nur Ifür Inhibit Interperetation / Conversion von Objekten scheint ein bisschen zu kurz :)
sertsedat
@pwilcox sehr interessant. Gibt es eine Methode, um ein Objekt aufzurufen, um zu verstehen, ob es von mir geschützt wird? Ich denke es ist class()? zB I(iris) -> i; i %>% class() 3 [1] "AsIs" "data.frame"(gibt die AsIs-Klasse zurück)
stevec
33

Wenn Sie mit arbeiten data.tables, können Sie den Anruf bei vermeidenI()

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
quelle
Dies ist ein unterschätztes Merkmal data.tablemit großem Abstand
Daten Prinzessin
22

data_frames (verschiedentlich genannt tibbles, tbl_df, tbl) nativ die Erstellung von Listenspalten mit der Unterstützung data_frameKonstruktor. Für sie Last einen der vielen Bibliotheken mit ihnen zu verwenden wie tibble, dplyroder 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]>

Sie sind eigentlich data.framesunter der Haube, aber etwas modifiziert. Sie können fast immer wie gewohnt verwendet werden data.frames. Die einzige Ausnahme, die ich gefunden habe, ist, dass Leute, die unangemessene Klassenprüfungen durchführen, Probleme verursachen:

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

Ich empfehle, darüber in R 4 Data Science (kostenlos) zu lesen .

CoderGuy123
quelle
1
R bewegt sich und wächst und ich denke, dies ist die Antwort von 2018 auf die Frage und sollte irgendwie als solche gekennzeichnet werden.
Fitzroy Hogsflesh
Wenn es populär genug ist, wird es nach oben steigen. Viele von uns benutzen immer noch Base R ...
Ben Bolker