2016-08-20 1 views
19

Ich habe einen langen Formulardatenrahmen mit mehreren Einträgen für dasselbe Datum und dieselbe Person.Verwendung von Spreads mit doppelten Bezeichnern für Zeilen

jj <- data.frame(month=rep(1:3,4), 
      student=rep(c("Amy", "Bob"), each=6), 
      A=c(9, 7, 6, 8, 6, 9, 3, 2, 1, 5, 6, 5), 
      B=c(6, 7, 8, 5, 6, 7, 5, 4, 6, 3, 1, 5)) 

will ich es breite Form zu bringen und es so machen:

month Amy.A Bob.A Amy.B Bob.B 
1  
2  
3 
1 
2 
3 
1 
2 
3 
1 
2 
3 

Meine Frage an this sehr ähnlich ist.

kk <- jj %>% 
    gather(variable, value, -(month:student)) %>% 
    unite(temp, student, variable) %>% 
    spread(temp, value) 

aber es gibt folgende Fehlermeldung:: Ich habe den gegebenen Code in der Antwort verwendet

Error: Duplicate identifiers for rows (1, 4), (2, 5), (3, 6), (13, 16), (14, 17), (15, 18), (7, 10), (8, 11), (9, 12), (19, 22), (20, 23), (21, 24)

Vielen Dank im Voraus. Hinweis: Ich möchte nicht mehrere Einträge löschen.

+0

Der Ausgang ist nicht sinnvoll. Wie ist Bob.B '5 6 7'. Es gibt zwei Bob B Werte für Monat 1, '5 3'? Und für Monat 2 ist es "4 und 2". Endlich für Monat 3 '6 5'. Sie fassen diese zu einem Wert zusammen. –

Antwort

14

Das Problem ist die zwei Spalten für beide A und B. Wenn wir diese Spalte mit einem Wert erstellen können, können wir die Daten wie gewünscht verteilen. Sehen Sie sich die Ausgabe für jj_melt an, wenn Sie den folgenden Code verwenden.

library(reshape2) 
jj_melt <- melt(jj, id=c("month", "student")) 
jj_spread <- dcast(jj_melt, month ~ student + variable, value.var="value", fun=sum) 
# month Amy_A Amy_B Bob_A Bob_B 
# 1  1 17 11  8  8 
# 2  2 13 13  8  5 
# 3  3 15 15  6 11 

Ich will das nicht als Duplikat markieren, da die andere Frage nicht von sum zusammenfassen hat, aber die data.table Antwort könnte mit einem zusätzlichen Argumente helfen, fun=sum:

library(data.table) 
dcast(setDT(jj), month ~ student, value.var=c("A", "B"), fun=sum) 
# month A_sum_Amy A_sum_Bob B_sum_Amy B_sum_Bob 
# 1:  1  17   8  11   8 
# 2:  2  13   8  13   5 
# 3:  3  15   6  15  11 

Wenn Sie möchten, Um die tidyr Lösung zu verwenden, kombinieren Sie sie mit dcast, um durch sum zusammenzufassen.

as.data.frame(jj) 
library(tidyr) 
jj %>% 
    gather(variable, value, -(month:student)) %>% 
    unite(temp, student, variable) %>% 
    dcast(month ~ temp, fun=sum) 
# month Amy_A Amy_B Bob_A Bob_B 
# 1  1 17 11  8  8 
# 2  2 13 13  8  5 
# 3  3 15 15  6 11 

bearbeiten

Basierend auf Ihren neuen Anforderungen, ich habe eine Aktivität Spalte hinzugefügt.

library(dplyr) 
jj %>% group_by(month, student) %>% 
    mutate(id=1:n()) %>% 
    melt(id=c("month", "id", "student")) %>% 
    dcast(... ~ student + variable, value.var="value") 
# month id Amy_A Amy_B Bob_A Bob_B 
# 1  1 1  9  6  3  5 
# 2  1 2  8  5  5  3 
# 3  2 1  7  7  2  4 
# 4  2 2  6  6  6  1 
# 5  3 1  6  8  1  6 
# 6  3 2  9  7  5  5 

Die anderen Lösungen können ebenfalls verwendet werden. Hier habe ich einen optionalen Ausdruck die endgültige Ausgabe von Vorgangsnummer zu ordnen:

library(tidyr) 
jj %>% 
    gather(variable, value, -(month:student)) %>% 
    unite(temp, student, variable) %>% 
    group_by(temp) %>% 
    mutate(id=1:n()) %>% 
    dcast(... ~ temp) %>% 
    arrange(id) 
# month id Amy_A Amy_B Bob_A Bob_B 
# 1  1 1  9  6  3  5 
# 2  2 2  7  7  2  4 
# 3  3 3  6  8  1  6 
# 4  1 4  8  5  5  3 
# 5  2 5  6  6  6  1 
# 6  3 6  9  7  5  5 

Die data.table Syntax ist kompakt, da es für mehrere value.var Spalten erlaubt und wird von der Ausbreitung für uns kümmern. Wir können dann den Prozess melt -> cast überspringen.

library(data.table) 
setDT(jj)[, activityID := rowid(student)] 
dcast(jj, ... ~ student, value.var=c("A", "B")) 
# month activityID A_Amy A_Bob B_Amy B_Bob 
# 1:  1   1  9  3  6  5 
# 2:  1   4  8  5  5  3 
# 3:  2   2  7  2  7  4 
# 4:  2   5  6  6  6  1 
# 5:  3   3  6  1  8  6 
# 6:  3   6  9  5  7  5 
+0

Danke für die Antwort. Ich möchte nicht summieren. Es ist keine arithmetische Operation erforderlich.Ich möchte A- und B-Spalten für Amy, A- und B-Spalten für Bob erstellen, die einfach ihre jeweiligen Werte haben. –

+1

Wenn es zwei Werte für denselben Monat, Student und Klasse gibt, welchen möchten Sie auswählen? –

+0

Ich möchte beides. Eigentlich habe ich es mit Geld- und Briefdaten zu tun und daher gibt es mehrere Einträge. –

10

Ihre Antwort fehlte mutierte ID! Hier ist die Lösung mit nur dplyr Packge.

jj %>% 
    gather(variable, value, -(month:student)) %>% 
    unite(temp, student, variable) %>% 
    group_by(temp) %>% 
    mutate(id=1:n()) %>% 
    spread(temp, value) 
# A tibble: 6 x 6 
# month id Amy_A Amy_B Bob_A Bob_B 
# * <int> <int> <dbl> <dbl> <dbl> <dbl> 
# 1  1  1  9  6  3  5 
# 2  1  4  8  5  5  3 
# 3  2  2  7  7  2  4 
# 4  2  5  6  6  6  1 
# 5  3  3  6  8  1  6 
# 6  3  6  9  7  5  5 
+0

Wenn Sie die * id * -Spalte nicht möchten, fügen Sie am Ende einfach%%% select (-id) 'hinzu. – bonna

0
gather(data, key = "key", value = "value", ..., na.rm = FALSE, 
    convert = FALSE, factor_key = FALSE) 

Überprüfen Sie, ob Sie den Schlüssel und den Wert invertiert. "Key" ist der Name des neuen Schlüssels und "value" ist der tatsächliche Wert.

Verwandte Themen