Es kann sein, dass man in die Situation kommt verschiedene Datensätze miteinander kombinieren zu wollen. In einer Tabelle steht vielleicht für verschiedene Lebensmittel die Energiewerte und Vitamingehalte und in einer anderen Tabelle steht wie viel von welchem Lebensmittel eine Person gegessen hat. Will man jetzt schnell berechnen, wie viele kcal jede Person zu sich genommen hat kann man das schnell und elegant durch mergen der Datensätze, gefolgt von aggregate() um die kcal für jeden Patienten zusammenzurechnen.
Das ist natürlich nur ein dämliches Beispiel. Der geneigte R-Nutzer wird schon seine eigenen Anwendungen finden. Oft ist es auch viel einfacher Berechnungen an einem Datensatz durchzuführen als Funktionen zu basteln, die sich Daten aus mehreren Datensätzen zusammensuchen.
Das einfachste Beispiel
wie man es auch in jeder Datenbanken/Informationssysteme-Vorlesung vorgesetzt bekommt:
Wir haben zwei Tabellen, welche sich in einer Spalte ein Merkmal teilen.
Erzeugen wir so ein Beispiel in R:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| kartoffeln <- cbind.data.frame(sorte=c("Adretta","Amflora","Markies"), kgpreis=c(1.44,0.76,1.10))
einkauf <- cbind.data.frame(sorte=c("Adretta","Adretta","Amflora","Markies","Amflora"), kunde=c("Huber","Meyer","Meyer","Schmidt","Huber"),kg=c(10,23,5,8,6))
kartoffeln
# sorte kgpreis
# 1 Adretta 1.44
# 2 Amflora 0.76
# 3 Markies 1.10
einkauf
# sorte kunde kg
# 1 Adretta Huber 10
# 2 Adretta Meyer 23
# 3 Amflora Meyer 5
# 4 Markies Schmidt 8
# 5 Amflora Huber 6 |
Jetzt wird schnell klar, was wir haben möchten; Eine Tabelle die für jeden Kunden zeigt, was er bezahlen soll.
18
19
20
21
22
23
24
25
26
| einkaufmitpreis <- merge(kartoffeln,einkauf)
einkaufmitpreis$zuzahlen <- einkaufmitpreis$kgpreis * einkaufmitpreis$kg
einkaufmitpreis
# sorte kgpreis kunde kg zuzahlen
# 1 Adretta 1.44 Huber 10 14.40
# 2 Adretta 1.44 Meyer 23 33.12
# 3 Amflora 0.76 Meyer 5 3.80
# 4 Amflora 0.76 Huber 6 4.56
# 5 Markies 1.10 Schmidt 8 8.80 |
Das sieht doch schon ganz knorke aus. Die kritiker werden vielleicht anmerken, dass jetzt ja jeder Kunde nur den zu zahlenden Preis für die Bestellung einer Kartoffelsorte weiß. Dem widmen wir uns später.
Zunächst schauen wir, was passiert, wenn ein Kunde eine Bestellung von gleicher Kartoffelsorte hinzufügt.
30
31
32
33
34
35
36
37
38
39
40
| einkauf2 <- rbind(einkauf,cbind.data.frame(sorte="Adretta",kunde="Huber",kg=4))
einkauf2mitpreis <- merge(kartoffeln,einkauf2)
einkauf2mitpreis$zuzahlen <- einkauf2mitpreis$kgpreis * einkauf2mitpreis$kg
einkauf2mitpreis
# sorte kgpreis kunde kg zuzahlen
# 1 Adretta 1.44 Huber 10 14.40
# 2 Adretta 1.44 Meyer 23 33.12
# 3 Adretta 1.44 Huber 4 5.76
# 4 Amflora 0.76 Meyer 5 3.80
# 5 Amflora 0.76 Huber 6 4.56
# 6 Markies 1.10 Schmidt 8 8.80 |
Auch das funktioniert zuverlässig. Die Bestellung ist jetzt allerdings zwei mal in der Tabelle. Das bekommen wir jedoch leicht mit aggregate() heraus.
42
43
44
45
46
47
48
| aggregate(einkauf2mitpreis[,c("kg","zuzahlen")],by=einkauf2mitpreis[,c("sorte","kunde")],FUN=sum)
# sorte kunde kg zuzahlen
#1 Adretta Huber 14 20.16
#2 Amflora Huber 6 4.56
#3 Adretta Meyer 23 33.12
#4 Amflora Meyer 5 3.80
#5 Markies Schmidt 8 8.80 |
Jetzt sind die Bestellungen zusammengefasst. Derjenige, der die Kartoffeln einkauft interessiert sich vielleicht eher für:
50
51
52
53
54
| aggregate(kg~sorte,data=einkauf2mitpreis,sum)
# sorte kg
#1 Adretta 37
#2 Amflora 11
#3 Markies 8 |
So sollte es auch nicht schwer sein, andere Fragestellungen zu beantworten.
Wenn nicht alles passt
dann macht merge meistens vieles richtig. Fällt z.B. die Bestellung mit der Sorte Markies weg…
55
56
57
58
59
60
61
62
| einkauf3 <- einkauf2[-4,]
merge(x=kartoffeln ,y=einkauf3)
# sorte kgpreis kunde kg
# 1 Adretta 1.44 Huber 10
# 2 Adretta 1.44 Meyer 23
# 3 Adretta 1.44 Huber 4
# 4 Amflora 0.76 Meyer 5
# 5 Amflora 0.76 Huber 6 |
…dann ist sie auch einfach nicht mehr im Ergebnis.
Was ist jedoch, wenn es die Sorte Adretta nicht mehr gäbe. Nicht auszudenken, wenn dann die Bestellungen einfach wegfallen.
64
65
66
67
68
69
70
71
72
73
| wenigerkartoffeln <- kartoffeln[-1,]
merge(x=einkauf2, y=wenigerkartoffeln) #Das ist blöd, denn wir wollen die Bestellung ja nicht vergessen
merge(x=einkauf2, y=wenigerkartoffeln, all.x=T) #Schon besser.
# sorte kunde kg kgpreis
# 1 Adretta Huber 10 NA
# 2 Adretta Meyer 23 NA
# 3 Adretta Huber 4 NA
# 4 Amflora Meyer 5 0.76
# 5 Amflora Huber 6 0.76
# 6 Markies Schmidt 8 1.10 |
Gut. Dieses Problem ist geklärt. Doch weiteres Unheil kann auf uns zukommen! Im echten Leben stimmen die Spaltennamen selten überein. Was nun?
77
78
79
80
81
82
83
84
85
86
| einkauf4 <- einkauf2
colnames(einkauf4)[1] <- "Kartoffelsorte"
merge(x=einkauf4, y=wenigerkartoffeln, all.x=T, by.x="Kartoffelsorte", by.y="sorte") #perfekt
# sorte kunde kg kgpreis
# 1 Adretta Huber 10 NA
# 2 Adretta Meyer 23 NA
# 3 Adretta Huber 4 NA
# 4 Amflora Meyer 5 0.76
# 5 Amflora Huber 6 0.76
# 6 Markies Schmidt 8 1.10 |
Kleine Anmerkung zum Schluß: Natürlich kann man auch all.x=T und all.y=T gleichzeitig nutzen.