Update 2017-08-03
หลังจากเขียนสิ่งนี้ Hadley ได้เปลี่ยนบางสิ่งอีกครั้ง ฟังก์ชั่นที่เคยอยู่ใน purrr ตอนนี้อยู่ในแพ็คเกจผสมใหม่ที่เรียกว่าpurrrlyrซึ่งอธิบายว่า:
purrrlyr มีฟังก์ชันบางอย่างที่อยู่ตรงจุดตัดของ purrr และ dplyr พวกเขาถูกลบออกจากเสียงฟี้ดเพื่อให้แพคเกจมีน้ำหนักเบาและเนื่องจากถูกแทนที่ด้วยโซลูชันอื่น ๆ ใน tidyverse
ดังนั้นคุณจะต้องติดตั้ง + โหลดแพ็คเกจนั้นเพื่อให้โค้ดด้านล่างใช้งานได้
โพสต์ต้นฉบับ
Hadley มักจะเปลี่ยนใจเกี่ยวกับสิ่งที่เราควรใช้ แต่ฉันคิดว่าเราควรจะเปลี่ยนไปใช้ฟังก์ชั่นในpurrrเพื่อรับฟังก์ชันทีละแถว อย่างน้อยพวกเขามีฟังก์ชันการทำงานที่เหมือนกันและมีเกือบอินเตอร์เฟซเดียวกันเป็นadply
จากplyr
มีสองฟังก์ชันที่เกี่ยวข้องby_row
และinvoke_rows
. ความเข้าใจของฉันคือคุณใช้by_row
เมื่อคุณต้องการวนซ้ำแถวและเพิ่มผลลัพธ์ลงใน data.frame invoke_rows
ใช้เมื่อคุณวนซ้ำแถวของ data.frame และส่งแต่ละ col เป็นอาร์กิวเมนต์ไปยังฟังก์ชัน เราจะใช้ครั้งแรกเท่านั้น
ตัวอย่าง
library(tidyverse)
iris %>%
by_row(..f = function(this_row) {
browser()
})
นี้จะช่วยให้เราเห็น internals (เพื่อเราจะได้เห็นสิ่งที่เรากำลังทำอยู่) adply
ซึ่งเป็นเช่นเดียวกับการทำมันด้วย
Called from: ..f(.d[[i]], ...)
Browse[1]> this_row
# A tibble: 1 × 5
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
<dbl> <dbl> <dbl> <dbl> <fctr>
1 5.1 3.5 1.4 0.2 setosa
Browse[1]> Q
ตามค่าเริ่มต้นby_row
จะเพิ่มคอลัมน์รายการตามผลลัพธ์:
iris %>%
by_row(..f = function(this_row) {
this_row[1:4] %>% unlist %>% mean
})
ให้:
# A tibble: 150 × 6
Sepal.Length Sepal.Width Petal.Length Petal.Width Species .out
<dbl> <dbl> <dbl> <dbl> <fctr> <list>
1 5.1 3.5 1.4 0.2 setosa <dbl [1]>
2 4.9 3.0 1.4 0.2 setosa <dbl [1]>
3 4.7 3.2 1.3 0.2 setosa <dbl [1]>
4 4.6 3.1 1.5 0.2 setosa <dbl [1]>
5 5.0 3.6 1.4 0.2 setosa <dbl [1]>
6 5.4 3.9 1.7 0.4 setosa <dbl [1]>
7 4.6 3.4 1.4 0.3 setosa <dbl [1]>
8 5.0 3.4 1.5 0.2 setosa <dbl [1]>
9 4.4 2.9 1.4 0.2 setosa <dbl [1]>
10 4.9 3.1 1.5 0.1 setosa <dbl [1]>
# ... with 140 more rows
ถ้าเราส่งคืน a แทนเราdata.frame
จะได้รับรายการด้วยdata.frame
s:
iris %>%
by_row( ..f = function(this_row) {
data.frame(
new_col_mean = this_row[1:4] %>% unlist %>% mean,
new_col_median = this_row[1:4] %>% unlist %>% median
)
})
ให้:
# A tibble: 150 × 6
Sepal.Length Sepal.Width Petal.Length Petal.Width Species .out
<dbl> <dbl> <dbl> <dbl> <fctr> <list>
1 5.1 3.5 1.4 0.2 setosa <data.frame [1 × 2]>
2 4.9 3.0 1.4 0.2 setosa <data.frame [1 × 2]>
3 4.7 3.2 1.3 0.2 setosa <data.frame [1 × 2]>
4 4.6 3.1 1.5 0.2 setosa <data.frame [1 × 2]>
5 5.0 3.6 1.4 0.2 setosa <data.frame [1 × 2]>
6 5.4 3.9 1.7 0.4 setosa <data.frame [1 × 2]>
7 4.6 3.4 1.4 0.3 setosa <data.frame [1 × 2]>
8 5.0 3.4 1.5 0.2 setosa <data.frame [1 × 2]>
9 4.4 2.9 1.4 0.2 setosa <data.frame [1 × 2]>
10 4.9 3.1 1.5 0.1 setosa <data.frame [1 × 2]>
# ... with 140 more rows
วิธีที่เราเพิ่มเอาต์พุตของฟังก์ชันนั้นถูกควบคุมโดย.collate
พารามิเตอร์ มีสามตัวเลือก: รายการแถวคอลัมน์ เมื่อเอาต์พุตของเรามีความยาว 1 ไม่สำคัญว่าเราจะใช้แถวหรือคอลัมน์
iris %>%
by_row(.collate = "cols", ..f = function(this_row) {
this_row[1:4] %>% unlist %>% mean
})
iris %>%
by_row(.collate = "rows", ..f = function(this_row) {
this_row[1:4] %>% unlist %>% mean
})
ทั้งสองผลิต:
# A tibble: 150 × 6
Sepal.Length Sepal.Width Petal.Length Petal.Width Species .out
<dbl> <dbl> <dbl> <dbl> <fctr> <dbl>
1 5.1 3.5 1.4 0.2 setosa 2.550
2 4.9 3.0 1.4 0.2 setosa 2.375
3 4.7 3.2 1.3 0.2 setosa 2.350
4 4.6 3.1 1.5 0.2 setosa 2.350
5 5.0 3.6 1.4 0.2 setosa 2.550
6 5.4 3.9 1.7 0.4 setosa 2.850
7 4.6 3.4 1.4 0.3 setosa 2.425
8 5.0 3.4 1.5 0.2 setosa 2.525
9 4.4 2.9 1.4 0.2 setosa 2.225
10 4.9 3.1 1.5 0.1 setosa 2.400
# ... with 140 more rows
หากเราส่งออก data.frame ด้วย 1 แถวจะมีความสำคัญเพียงเล็กน้อยที่เราใช้
iris %>%
by_row(.collate = "cols", ..f = function(this_row) {
data.frame(
new_col_mean = this_row[1:4] %>% unlist %>% mean,
new_col_median = this_row[1:4] %>% unlist %>% median
)
})
iris %>%
by_row(.collate = "rows", ..f = function(this_row) {
data.frame(
new_col_mean = this_row[1:4] %>% unlist %>% mean,
new_col_median = this_row[1:4] %>% unlist %>% median
)
})
ทั้งสองให้:
# A tibble: 150 × 8
Sepal.Length Sepal.Width Petal.Length Petal.Width Species .row new_col_mean new_col_median
<dbl> <dbl> <dbl> <dbl> <fctr> <int> <dbl> <dbl>
1 5.1 3.5 1.4 0.2 setosa 1 2.550 2.45
2 4.9 3.0 1.4 0.2 setosa 2 2.375 2.20
3 4.7 3.2 1.3 0.2 setosa 3 2.350 2.25
4 4.6 3.1 1.5 0.2 setosa 4 2.350 2.30
5 5.0 3.6 1.4 0.2 setosa 5 2.550 2.50
6 5.4 3.9 1.7 0.4 setosa 6 2.850 2.80
7 4.6 3.4 1.4 0.3 setosa 7 2.425 2.40
8 5.0 3.4 1.5 0.2 setosa 8 2.525 2.45
9 4.4 2.9 1.4 0.2 setosa 9 2.225 2.15
10 4.9 3.1 1.5 0.1 setosa 10 2.400 2.30
# ... with 140 more rows
ยกเว้นว่าคอลัมน์ที่สองมีการเรียกคอลัมน์.row
และคอลัมน์แรกไม่มี
สุดท้ายหากผลลัพธ์ของเรายาวกว่าความยาว 1 ไม่ว่าจะเป็น a vector
หรือเป็นdata.frame
แถวก็มีความสำคัญไม่ว่าเราจะใช้แถวหรือคอลัมน์สำหรับ.collate
:
mtcars[1:2] %>% by_row(function(x) 1:5)
mtcars[1:2] %>% by_row(function(x) 1:5, .collate = "rows")
mtcars[1:2] %>% by_row(function(x) 1:5, .collate = "cols")
ผลิตตามลำดับ:
# A tibble: 32 × 3
mpg cyl .out
<dbl> <dbl> <list>
1 21.0 6 <int [5]>
2 21.0 6 <int [5]>
3 22.8 4 <int [5]>
4 21.4 6 <int [5]>
5 18.7 8 <int [5]>
6 18.1 6 <int [5]>
7 14.3 8 <int [5]>
8 24.4 4 <int [5]>
9 22.8 4 <int [5]>
10 19.2 6 <int [5]>
# ... with 22 more rows
# A tibble: 160 × 4
mpg cyl .row .out
<dbl> <dbl> <int> <int>
1 21 6 1 1
2 21 6 1 2
3 21 6 1 3
4 21 6 1 4
5 21 6 1 5
6 21 6 2 1
7 21 6 2 2
8 21 6 2 3
9 21 6 2 4
10 21 6 2 5
# ... with 150 more rows
# A tibble: 32 × 7
mpg cyl .out1 .out2 .out3 .out4 .out5
<dbl> <dbl> <int> <int> <int> <int> <int>
1 21.0 6 1 2 3 4 5
2 21.0 6 1 2 3 4 5
3 22.8 4 1 2 3 4 5
4 21.4 6 1 2 3 4 5
5 18.7 8 1 2 3 4 5
6 18.1 6 1 2 3 4 5
7 14.3 8 1 2 3 4 5
8 24.4 4 1 2 3 4 5
9 22.8 4 1 2 3 4 5
10 19.2 6 1 2 3 4 5
# ... with 22 more rows
ดังนั้นบรรทัดล่าง หากคุณต้องการadply(.margins = 1, ...)
ฟังก์ชั่นคุณสามารถใช้by_row
.
mdply
ใน dplyrdo
และฮัดลีย์บอกว่าพวกเขาอาจจะมีบางสิ่งบางอย่างขึ้นอยู่กับการผลิตเบียร์ ฉันเดาว่ามันก็น่าจะใช้ได้เช่นกัน