2016-05-04 6 views
1

Ich habe einen Datensatz wie folgt aus:subtrahieren Reihen von Zeit und ID

set.seed(10) 
df <- data.frame(
Year = rep(2000, times=16), 
Month = rep(1:2, each=8), 
group = rep(c("ABC","ABc","Abc","AbC","aBC","aBc","abc", "abC"),times=2), 
A_gr = rep(c("A","A","A","A","a","a","a","a"), times=2), 
V = rnorm(16) 
) 

Wo A, B und C kann entweder in Form eines Kapitals oder einen kleinen Buchstaben haben. Für jeden Zeitpunkt (Monat + Jahr) und Gruppenkombination möchte ich nun den V-Wert der Großbuchstabenversion von der Kleinbuchstabenversion subtrahieren. Also aBC-ABC, aBc-ABc usw.

Mit nur 2 Gruppenbriefen habe ich das mit der Reihenfolge, Liste und nach getan, aber ich kann das hier nicht machen. Ich habe auch mit Plyr experimentiert, bin aber auch nicht erfolgreich gewesen. Irgendwelche Ideen?

Weiter frage ich mich, ob es möglich ist, die Summe aller vier Großbuchstaben von der Summe der Kleinbuchstaben in einem Schritt zu subtrahieren, also (ABC + ABC + ABC + ABC) - (ABC + ABc + ABC) + AbC)

Antwort

2

Wir könnten dies auch mit data.table tun. Konvertieren Sie 'data.frame' in 'data.table' (setDT(df)), erstellen Sie eine andere Gruppierungsvariable ('gr'), indem Sie das erste Zeichen in 'group' in Großbuchstaben umwandeln, indem Sie sub verwenden, dann verwenden Sie das in der by zusammen mit ' Monat 'und' Jahr ', erhalten Sie den Unterschied zwischen' V ', das "A" und "a" in' A_gr 'entspricht, und weisen Sie' GR 'NULL zu (falls erforderlich).

library(data.table) 
setDT(df)[, .(group = paste(group[2L],group[1L], 
     sep="-"),Diffs=V[A_gr=="A"]- V[A_gr=="a"]), 
     by = .(gr=sub("(.)", "\\U\\1", group, perl=TRUE), Month, Year)][, gr:= NULL][] 
# Month Year group  Diffs 
#1:  1 2000 aBC-ABC -0.2757990 
#2:  1 2000 aBc-ABc -0.5740468 
#3:  1 2000 abc-Abc -0.1632544 
#4:  1 2000 abC-AbC -0.2354917 
#5:  2 2000 aBC-ABC -1.3884391 
#6:  2 2000 aBc-ABc -1.2439231 
#7:  2 2000 abc-Abc 0.3603894 
#8:  2 2000 abC-AbC 0.6664342 

Oder dcast aus data.table unter Verwendung von 'langen' aus 'breit' Format zu konvertieren, nachdem sie durch eine andere Variable ('GR') die Schaffung der substring in 'Gruppe' zu extrahieren. Wir nehmen den Unterschied zwischen den Spalten "V_A" und "V_a" vom dcast-Ausgang.

setDT(df)[, gr:= substring(group, 2)] 
dcast(df, Year+Month+gr~A_gr, value.var=c("V", "group"))[, 
    .(group = paste(group_A, group_a, sep="-"), Diffs = V_A- V_a), .(Year, Month)] 
# Year Month group  Diffs 
#1: 2000  1 ABC-aBC -0.2757990 
#2: 2000  1 ABc-aBc -0.5740468 
#3: 2000  1 AbC-abC -0.2354917 
#4: 2000  1 Abc-abc -0.1632544 
#5: 2000  2 ABC-aBC -1.3884391 
#6: 2000  2 ABc-aBc -1.2439231 
#7: 2000  2 AbC-abC 0.6664342 
#8: 2000  2 Abc-abc 0.3603894 
+0

Danke für diese Lösung! Nur um mehr über die Dynamik des Codes zu verstehen: Wofür stehen die "\\ U \\ 1" - und Perl-Argumente in Lösung 1 und wofür steht die 2 im Teilstring-Befehl in Lösung 2? – faremi

+0

@faremi Das '\\ U \\ 1' steht für die Umwandlung der erfassten Gruppe in Großbuchstaben. '\\ 1' ist die Rückreferenz für die erfasste Gruppe (' (.) '), Es passt zum ersten Zeichen und wird in Großbuchstaben umgewandelt. In der 'Teilzeichenfolge 'verwenden wir die' Start'-Position als 2. So werden alle Zeichen von 2 bis Ende der Zeichenkette extrahiert. – akrun

+0

Das macht Sinn! Etwas Neues gelernt. :) Gibt es eine intelligentere Lösung, um das zu tun, was ich in meiner Follow-up-Frage beschrieben habe, als deinen Algorithmus viermal anzuwenden? – faremi

2

Hier ist ein Weg, um Ihre Daten zu verwandeln, indem die a oder A Informationen aus der Gruppe Spalt zu entfernen, da sie auch von A_gr vorgesehen ist, und dann tidyr Paket verwenden, um die Daten long-wide Format zu umwandeln, die es macht viel einfacher, den Unterschied zu berechnen.

library(dplyr); library(tidyr) 
df %>% mutate(group = gsub("[A|a]", "", group)) %>% 
     spread(A_gr, V) %>% mutate(diffV = A - a) %>% 
     select(Year, Month, group, diffV) 

    Year Month group diffV 
1 2000  1 bc -0.16325 
2 2000  1 bC -0.23549 
3 2000  1 Bc -0.57405 
4 2000  1 BC -0.27580 
5 2000  2 bc 0.36039 
6 2000  2 bC 0.66643 
7 2000  2 Bc -1.24392 
8 2000  2 BC -1.38844 
+0

Vielen Dank für diese intelligente Lösung! Löst das auch meine bearbeitete Folgefrage? – faremi