เนื่องจากฉันตระหนักว่าคำตอบที่ยอดเยี่ยมมากของการขาดโพสต์by
และaggregate
คำอธิบาย นี่คือผลงานของฉัน
จำแนกตาม
by
ฟังก์ชั่นตามที่ระบุไว้ในเอกสารที่สามารถ แต่เป็น "เสื้อคลุม" tapply
สำหรับ พลังของการby
เกิดขึ้นเมื่อเราต้องการคำนวณงานที่tapply
ไม่สามารถจัดการได้ ตัวอย่างหนึ่งคือรหัสนี้:
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
ถ้าเราพิมพ์ทั้งสองวัตถุct
และcb
เรา "หลัก" มีผลที่เหมือนกันและแตกต่างเพียง แต่ในวิธีการที่พวกเขาจะแสดงให้เห็นที่แตกต่างกันและclass
คุณลักษณะตามลำดับby
สำหรับcb
และสำหรับarray
ct
เป็นฉันได้กล่าวว่าอำนาจของby
เกิดขึ้นเมื่อเราไม่สามารถใช้tapply
; รหัสต่อไปนี้เป็นตัวอย่างหนึ่ง:
tapply(iris, iris$Species, summary )
Error in tapply(iris, iris$Species, summary) :
arguments must have same length
R บอกว่าอาร์กิวเมนต์ต้องมีความยาวเท่ากันพูดว่า "เราต้องการคำนวณsummary
ตัวแปรทั้งหมดiris
ตามปัจจัยSpecies
": แต่ R ไม่สามารถทำได้เพราะไม่ทราบวิธีจัดการ
ด้วยby
ฟังก์ชั่น R ส่งวิธีการเฉพาะสำหรับการdata frame
เรียนแล้วปล่อยให้summary
ฟังก์ชั่นการทำงานแม้ว่าความยาวของอาร์กิวเมนต์แรก (และประเภทเกินไป) จะแตกต่างกัน
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
มันใช้งานได้จริงและผลลัพธ์ก็น่าประหลาดใจมาก มันเป็นวัตถุของคลาสby
ที่ตามSpecies
(พูดสำหรับแต่ละคน) คำนวณsummary
ของแต่ละตัวแปร
โปรดทราบว่าหากอาร์กิวเมนต์แรกคือ a data frame
ฟังก์ชันที่ถูกส่งจะต้องมีวิธีการสำหรับคลาสของวัตถุนั้น ตัวอย่างเช่นเราใช้รหัสนี้กับmean
ฟังก์ชั่นเราจะมีรหัสนี้ที่ไม่มีความหมายเลย:
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
AGGREGATE
aggregate
สามารถถูกมองว่าเป็นอีกวิธีหนึ่งในการใช้งานที่แตกต่างกันtapply
หากเราใช้ในลักษณะดังกล่าว
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
ทั้งสองแตกต่างทันทีที่อาร์กิวเมนต์ที่สองของการaggregate
ต้องเป็นรายการในขณะที่tapply
สามารถ (ไม่จำเป็น) เป็นรายการและการส่งออกของaggregate
กรอบข้อมูลในขณะที่หนึ่งในเป็นtapply
array
พลังของaggregate
มันคือมันสามารถจัดการกับส่วนย่อยของข้อมูลได้อย่างง่ายดายด้วยการsubset
โต้แย้งและมันมีวิธีการสำหรับts
วัตถุและformula
เช่นกัน
องค์ประกอบเหล่านี้ทำให้aggregate
การทำงานกับมันง่ายขึ้นtapply
ในบางสถานการณ์ นี่คือตัวอย่าง (มีอยู่ในเอกสารประกอบ):
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
เราสามารถบรรลุผลได้เหมือนกันtapply
แต่ไวยากรณ์ยากขึ้นเล็กน้อยและเอาต์พุต (ในบางสถานการณ์) อ่านได้น้อยลง:
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
มีครั้งอื่น ๆ เมื่อเราไม่สามารถใช้เป็นby
หรือและเราจะต้องใช้tapply
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
เราไม่สามารถรับผลลัพธ์ก่อนหน้าด้วยการtapply
โทรครั้งเดียว แต่เราต้องคำนวณค่าเฉลี่ยMonth
สำหรับแต่ละองค์ประกอบแล้วรวมเข้าด้วยกัน (โปรดทราบว่าเราต้องเรียกใช้na.rm = TRUE
เพราะformula
วิธีการaggregate
ทำงานมีค่าเริ่มต้น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
ในขณะที่by
เราไม่สามารถบรรลุผลได้ในความเป็นจริงการเรียกใช้ฟังก์ชันต่อไปนี้ส่งคืนข้อผิดพลาด (แต่ส่วนใหญ่จะเกี่ยวข้องกับฟังก์ชันที่ให้มาmean
):
by(airquality[c("Ozone", "Temp")], airquality$Month, mean, na.rm = TRUE)
บางครั้งผลลัพธ์จะเหมือนกันและความแตกต่างอยู่ในคลาส (และวิธีแสดง / พิมพ์และไม่เพียง - ตัวอย่างเช่นวิธีการย่อย) วัตถุ:
byagg <- by(airquality[c("Ozone", "Temp")], airquality$Month, summary)
aggagg <- aggregate(cbind(Ozone, Temp) ~ Month, data = airquality, summary)
รหัสก่อนหน้านี้บรรลุเป้าหมายและผลลัพธ์เดียวกันในบางจุดเครื่องมือที่ใช้เป็นเรื่องของรสนิยมและความต้องการส่วนบุคคล วัตถุสองชิ้นก่อนหน้ามีความต้องการที่แตกต่างกันมากในแง่ของการย่อย
*apply()
by
plyr (อย่างน้อยสำหรับฉัน) ดูเหมือนจะสอดคล้องกันมากขึ้นในการที่ฉันมักจะรู้ว่าสิ่งที่รูปแบบข้อมูลที่คาดหวังและสิ่งที่มันจะคายออก ที่ช่วยให้ฉันยุ่งยากมาก