2015-05-14 7 views
14

Mein Datenrahmen enthält die Ausgabe einer Umfrage mit einem ausgewählten mehreren Fragetyp. Einige Zellen haben mehrere Werte.Abflachungslistenspalte im Datenrahmen mit ID-Spalte

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

Ich möchte die Liste verflachen die folgende Ausgabe zu erhalten:

df 
    a  b 
1 1  1 
2 2  1 
3 2  2 
4 3  1 
5 3  2 
6 3  3 

sollte einfach sein, aber irgendwie kann ich nicht die Suchbegriffe finden. Vielen Dank.

Antwort

16

Sie können nur unnest von "tidyr" verwenden:

library(tidyr) 
unnest(df, b) 
# a b 
# 1 1 1 
# 2 2 1 
# 3 2 2 
# 4 3 1 
# 5 3 2 
# 6 3 3 
+0

danke! perfekt, ich habe tidyr angeschaut, aber diesen speziellen fall nicht gefunden – mloudon

+0

Das OP sagte, dass es einfach sein sollte, und du hast bewiesen, dass es wirklich so einfach ist! Gute Arbeit! –

7

Mit base R, eine Option ist stack nach der list Elemente von 'b' Spalte mit der der Elemente von 'a' zu nennen. Wir können setNames verwenden, um die Namen zu ändern.

stack(setNames(df$b, df$a)) 

Oder eine andere Möglichkeit wäre, unstack zu verwenden, um automatisch das Listenelement von ‚b‘ zu nennen mit ‚a‘ Elemente und führen Sie dann die stack eine data.frame Ausgabe zu erhalten.

stack(unstack(df, b~a)) 

Oder können wir eine komfortable Funktion listCol_l von splitstackshape verwenden, um die list-data.frame zu konvertieren.

library(splitstackshape) 
listCol_l(df, 'b') 
+2

Gute Arbeit. Ich liebe es immer, einfache, elegante Basislösungen zu sehen. –

4

Hier ist eine Art und Weise, mit data.table:

require(data.table) 
data.table(df)[,as.integer(unlist(b)),by=a] 

Wenn b konsequent gespeichert ist, as.integer übersprungen werden kann. Sie können mit

unique(sapply(df$b,class)) 
# [1] "numeric" "integer" 
+3

'df $ b [1] <- Liste (1L)' uns zu manuell und unpraktisch, wenn das OP viele solcher Einträge hat. Ich denke etwas wie "data.table (df) [, as.integer (unlist (b)), durch = a]" sollte tun –

+0

@DavidArenburg Ja, oder die Daten in R "richtig" (im Sinne von Speichern als Ganzzahlen im Vordergrund). Ich wechsle zu dem, was du geschrieben hast. – Frank

3

Hier ist eine andere Basislösung, weit weniger elegant als jede andere bisher veröffentlichte Lösung. Um der Vollständigkeit halber zu posten, würde ich persönlich die Basislösung von akrun empfehlen.

with(df, cbind(a = rep(a, sapply(b, length)), b = do.call(c, b))) 

Dies baut die erste Spalte als die Elemente des a, wobei jeder wiederholt aus b die Länge des entsprechenden Listeneintrags entsprechen. Die zweite Spalte ist b "abgeflacht" unter Verwendung do.call() mit c().

Wie Ananda Mahto in einem Kommentar darauf hingewiesen, sapply(b, length) kann mit lengths(b) in der neuesten Version von R (3.2, wenn ich mich nicht irre) ersetzt werden.

+3

In der neuesten Version von R können Sie 'sapply (b, length)' durch 'lengthes (b)' ersetzen. – A5C1D2H2I1M1N2O1R2T1

+0

@AnandaMahto: Das ist großartig, danke für die Köpfe hoch! –

+0

um eine data.frame zurück zu bekommen, würden Sie wahrscheinlich besser verwenden: 'mit (df, data.frame (a = rep (a, Längen (b)), b = unlist (b))) – Jaap

Verwandte Themen