Da habe ich festgestellt, dass (die sehr ausgezeichneten) Antworten dieses Beitrags fehlen byund aggregateErklärungen. Hier ist mein Beitrag.
DURCH
Die byin der Dokumentation angegebene Funktion kann jedoch als "Wrapper" für tapply. Die Kraft von byentsteht, wenn wir eine Aufgabe berechnen wollen, tapplydie nicht erledigt werden kann. Ein Beispiel ist dieser Code:
ct <- tapply(iris$Sepal.Width , iris$Species , summary )
cb <- by(iris$Sepal.Width , iris$Species , summary )
cb
iris$Species: setosa
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.300 3.200 3.400 3.428 3.675 4.400
--------------------------------------------------------------
iris$Species: versicolor
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.000 2.525 2.800 2.770 3.000 3.400
--------------------------------------------------------------
iris$Species: virginica
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.200 2.800 3.000 2.974 3.175 3.800
ct
$setosa
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.300 3.200 3.400 3.428 3.675 4.400
$versicolor
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.000 2.525 2.800 2.770 3.000 3.400
$virginica
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.200 2.800 3.000 2.974 3.175 3.800
Wenn wir diese beiden Objekte drucken ctund cb"im Wesentlichen" die gleichen Ergebnisse erzielen und die einzigen Unterschiede darin bestehen, wie sie angezeigt werden und in welchen unterschiedlichen classAttributen byfür cbund arrayfür ct.
Wie ich schon sagte, byentsteht die Kraft von , wenn wir nicht nutzen können tapply; Der folgende Code ist ein Beispiel:
tapply(iris, iris$Species, summary )
Error in tapply(iris, iris$Species, summary) :
arguments must have same length
R sagt, dass Argumente die gleiche Länge haben müssen, sagen wir "wir wollen die summaryaller Variablen irisentlang des Faktors berechnen Species": aber R kann das einfach nicht, weil es nicht weiß, wie es zu handhaben ist.
Mit der byFunktion R wird eine bestimmte Methode für die data frameKlasse ausgelöst und die summaryFunktion dann auch dann funktionieren gelassen , wenn die Länge des ersten Arguments (und auch der Typ) unterschiedlich sind.
bywork <- by(iris, iris$Species, summary )
bywork
iris$Species: setosa
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
Min. :4.300 Min. :2.300 Min. :1.000 Min. :0.100 setosa :50
1st Qu.:4.800 1st Qu.:3.200 1st Qu.:1.400 1st Qu.:0.200 versicolor: 0
Median :5.000 Median :3.400 Median :1.500 Median :0.200 virginica : 0
Mean :5.006 Mean :3.428 Mean :1.462 Mean :0.246
3rd Qu.:5.200 3rd Qu.:3.675 3rd Qu.:1.575 3rd Qu.:0.300
Max. :5.800 Max. :4.400 Max. :1.900 Max. :0.600
--------------------------------------------------------------
iris$Species: versicolor
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
Min. :4.900 Min. :2.000 Min. :3.00 Min. :1.000 setosa : 0
1st Qu.:5.600 1st Qu.:2.525 1st Qu.:4.00 1st Qu.:1.200 versicolor:50
Median :5.900 Median :2.800 Median :4.35 Median :1.300 virginica : 0
Mean :5.936 Mean :2.770 Mean :4.26 Mean :1.326
3rd Qu.:6.300 3rd Qu.:3.000 3rd Qu.:4.60 3rd Qu.:1.500
Max. :7.000 Max. :3.400 Max. :5.10 Max. :1.800
--------------------------------------------------------------
iris$Species: virginica
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
Min. :4.900 Min. :2.200 Min. :4.500 Min. :1.400 setosa : 0
1st Qu.:6.225 1st Qu.:2.800 1st Qu.:5.100 1st Qu.:1.800 versicolor: 0
Median :6.500 Median :3.000 Median :5.550 Median :2.000 virginica :50
Mean :6.588 Mean :2.974 Mean :5.552 Mean :2.026
3rd Qu.:6.900 3rd Qu.:3.175 3rd Qu.:5.875 3rd Qu.:2.300
Max. :7.900 Max. :3.800 Max. :6.900 Max. :2.500
es funktioniert in der Tat und das Ergebnis ist sehr überraschend. Es ist ein Objekt der Klasse by, das zusammen Species(etwa für jedes von ihnen) das summaryvon jeder Variablen berechnet .
Beachten Sie, dass data framedie ausgelöste Funktion eine Methode für diese Objektklasse haben muss , wenn das erste Argument a ist . Zum Beispiel verwenden wir diesen Code mit der meanFunktion, dass wir diesen Code haben, der überhaupt keinen Sinn hat:
by(iris, iris$Species, mean)
iris$Species: setosa
[1] NA
-------------------------------------------
iris$Species: versicolor
[1] NA
-------------------------------------------
iris$Species: virginica
[1] NA
Warning messages:
1: In mean.default(data[x, , drop = FALSE], ...) :
argument is not numeric or logical: returning NA
2: In mean.default(data[x, , drop = FALSE], ...) :
argument is not numeric or logical: returning NA
3: In mean.default(data[x, , drop = FALSE], ...) :
argument is not numeric or logical: returning NA
AGGREGAT
aggregatekann als eine andere Art der Verwendung angesehen werden, tapplywenn wir es so verwenden.
at <- tapply(iris$Sepal.Length , iris$Species , mean)
ag <- aggregate(iris$Sepal.Length , list(iris$Species), mean)
at
setosa versicolor virginica
5.006 5.936 6.588
ag
Group.1 x
1 setosa 5.006
2 versicolor 5.936
3 virginica 6.588
Die beiden unmittelbaren Unterschiede sind , dass das zweite Argument der aggregate muss eine Liste sein , während tapply kann (nicht zwingend) eine Liste sein und dass der Ausgang aggregateist ein Datenrahmen , während der eine von tapplyeinem ist array.
Die Stärke von aggregateist, dass es leicht Teilmengen der Daten mit subsetArgumenten verarbeiten kann und dass es Methoden für tsObjekte und formulaauch hat.
Diese Elemente aggregateerleichtern tapplyin einigen Situationen die Arbeit damit . Hier einige Beispiele (in der Dokumentation verfügbar):
ag <- aggregate(len ~ ., data = ToothGrowth, mean)
ag
supp dose len
1 OJ 0.5 13.23
2 VC 0.5 7.98
3 OJ 1.0 22.70
4 VC 1.0 16.77
5 OJ 2.0 26.06
6 VC 2.0 26.14
Wir können dasselbe erreichen, tapplyaber die Syntax ist etwas schwieriger und die Ausgabe (unter bestimmten Umständen) weniger lesbar:
att <- tapply(ToothGrowth$len, list(ToothGrowth$dose, ToothGrowth$supp), mean)
att
OJ VC
0.5 13.23 7.98
1 22.70 16.77
2 26.06 26.14
Es gibt andere Zeiten, in denen wir nicht verwenden können byoder tapplymüssen aggregate.
ag1 <- aggregate(cbind(Ozone, Temp) ~ Month, data = airquality, mean)
ag1
Month Ozone Temp
1 5 23.61538 66.73077
2 6 29.44444 78.22222
3 7 59.11538 83.88462
4 8 59.96154 83.96154
5 9 31.44828 76.89655
Wir können das vorherige Ergebnis nicht mit tapplyeinem Aufruf erhalten, aber wir müssen den Mittelwert Monthfür jedes Element berechnen und dann kombinieren (beachten Sie auch, dass wir das aufrufen müssen na.rm = TRUE, da die formulaMethoden der aggregateFunktion standardmäßig das haben na.action = na.omit):
ta1 <- tapply(airquality$Ozone, airquality$Month, mean, na.rm = TRUE)
ta2 <- tapply(airquality$Temp, airquality$Month, mean, na.rm = TRUE)
cbind(ta1, ta2)
ta1 ta2
5 23.61538 65.54839
6 29.44444 79.10000
7 59.11538 83.90323
8 59.96154 83.96774
9 31.44828 76.90000
Während bywir dies einfach nicht erreichen können, gibt der folgende Funktionsaufruf einen Fehler zurück (aber höchstwahrscheinlich hängt er mit der bereitgestellten Funktion zusammen mean):
by(airquality[c("Ozone", "Temp")], airquality$Month, mean, na.rm = TRUE)
In anderen Fällen sind die Ergebnisse gleich und die Unterschiede liegen nur in der Klasse (und dann, wie es angezeigt / gedruckt wird und nicht nur - Beispiel, wie man es untergibt) Objekt:
byagg <- by(airquality[c("Ozone", "Temp")], airquality$Month, summary)
aggagg <- aggregate(cbind(Ozone, Temp) ~ Month, data = airquality, summary)
Der vorherige Code erreicht das gleiche Ziel und die gleichen Ergebnisse. An einigen Stellen ist das zu verwendende Tool nur eine Frage des persönlichen Geschmacks und der persönlichen Bedürfnisse. Die beiden vorherigen Objekte haben sehr unterschiedliche Anforderungen an die Teilmenge.
*apply()undby. plyr (zumindest für mich) scheint viel konsistenter zu sein, da ich immer genau weiß, welches Datenformat es erwartet und was es genau ausspucken wird. Das erspart mir viel Ärger.