[R語言初學] R語言中的%>%是什麼?
0Last Updated on 2023-10-05
你有沒有看過R語言裡面 %>% 這個奇怪的符號?解釋給你聽!
接觸R語言已經有一段時間,常常會看到%>%
,一直覺得很奇怪不知道這是什麼意思嗎?看到別人的程式碼寫了好一長串,中間都用 %>%
串起來,想知道是怎麼運作的嗎?
我會在這篇文章介紹R語言程式碼中常見的管線運算子(pipe operator)%>%
,配上實際程式碼,帶你成為R語言裡的水管達人。
前言
如果你剛開始接觸R語言,一定有機會看到 3 個長相奇特的符號連在一起:%>%
。
它到底是什麼奇怪的東西?
介紹管線運算子
magrittr
套件中的管線運算子
管線運算子,出自於library(magrittr)
,是 tidyverse
裡面必備的元素。
顧名思義,它的作用有如水管,能夠把符號左方的物件傳送到右方的函數當中。
傳送到右方函數運算完畢後,物件不會停留定著,可以繼續傳送,不斷往後。
實際的 %>% 案例
我們利用鑽石資料集來解說 %>%
的用途。
library(tidyverse)
head(diamonds, 5)
#> # A tibble: 5 × 10
#> carat cut color clarity depth table price x y z
#> <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
#> 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43
#> 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31
#> 3 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31
#> 4 0.29 Premium I VS2 62.4 58 334 4.2 4.23 2.63
#> 5 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75
鑽石資料集裡面有 10 個欄位,包含克拉、顏色、價格等,在此不一一贅述。
如果我們想從中選取克拉、顏色、價格這 3 個欄位,可以利用 library(dplyr)
當中的 select()
# 不用 pipe
select(diamonds, carat, color, price)
#> # A tibble: 53,940 × 3
#> carat color price
#> <dbl> <ord> <int>
#> 1 0.23 E 326
#> 2 0.21 E 326
#> 3 0.23 E 327
#> 4 0.29 I 334
#> 5 0.31 J 335
#> 6 0.24 J 336
#> 7 0.24 I 336
#> 8 0.26 H 337
#> 9 0.22 E 337
#> 10 0.23 H 338
#> # ℹ 53,930 more rows
# 使用 pipe
diamonds %>% select(carat, color, price)
#> # A tibble: 53,940 × 3
#> carat color price
#> <dbl> <ord> <int>
#> 1 0.23 E 326
#> 2 0.21 E 326
#> 3 0.23 E 327
#> 4 0.29 I 334
#> 5 0.31 J 335
#> 6 0.24 J 336
#> 7 0.24 I 336
#> 8 0.26 H 337
#> 9 0.22 E 337
#> 10 0.23 H 338
#> # ℹ 53,930 more rows
從上面兩行程式碼對比,可以看出來,%>%
的意義就是,把 diamonds
這個資料集,向後傳送到 select()
裡面。
只看一行程式碼的差異不大,但如果我們在挑選欄位後,想要採取更多動作,例如增加欄位、篩選資料等,就能夠看出差異。
# 不用 pipe
filter(mutate(select(diamonds, carat, color, price), price_twd = price*30), price_twd >= 10000)
#> # A tibble: 53,937 × 4
#> carat color price price_twd
#> <dbl> <ord> <int> <dbl>
#> 1 0.29 I 334 10020
#> 2 0.31 J 335 10050
#> 3 0.24 J 336 10080
#> 4 0.24 I 336 10080
#> 5 0.26 H 337 10110
#> 6 0.22 E 337 10110
#> 7 0.23 H 338 10140
#> 8 0.3 J 339 10170
#> 9 0.23 J 340 10200
#> 10 0.22 F 342 10260
#> # ℹ 53,927 more rows
上面這段程式碼的讀法是由內往外讀。
我們先從最裡面的 select()
開始,它幫助我們挑出了 3 個欄位。
下一步 mutate()
,則是根據美元計價的 price
欄位,增加了以台幣計價的 price_twd
欄位。
再下一步 filter()
篩選台幣 1 萬元以上的鑽石,把不符條件的資料剔除。
我們很容易想像,如果接著還有 5 步、6 步,使用函數將原先的物件層層包裹,光是想要理解程式碼本身,就會十分困難。
改用 %>%
,一切都會輕鬆許多。
# 使用 pipe
diamonds %>%
select(carat, color, price) %>%
mutate(price_twd = price*30) %>%
filter(price_twd >= 10000)
#> # A tibble: 53,937 × 4
#> carat color price price_twd
#> <dbl> <ord> <int> <dbl>
#> 1 0.29 I 334 10020
#> 2 0.31 J 335 10050
#> 3 0.24 J 336 10080
#> 4 0.24 I 336 10080
#> 5 0.26 H 337 10110
#> 6 0.22 E 337 10110
#> 7 0.23 H 338 10140
#> 8 0.3 J 339 10170
#> 9 0.23 J 340 10200
#> 10 0.22 F 342 10260
#> # ℹ 53,927 more rows
diamonds
資料集從頭開始,經過一個又一個的函數,就像生產線一樣經過加工,而後呈現在我們面前。
不該使用 %>% 的時機
在R for Data Science 書中,有提醒讀者不該使用管線運算子的時機。
第一,若超過 10 個步驟時,避免自己讀錯程式碼,也方便糾錯,可以考慮在中間停下腳步,先把運算結果儲存到變數中。
第二,如果同時有多個輸入(input)或輸出(output)時,也最好不要用 %>%
。
第三,若使用情境並非線性(linear),可能是環環相扣,或者有複雜的相依性時,最好不要使用 %>%
。
我們最後再延伸一下上面的案例,展示 %>%
的威力吧!
# 使用 pipe
diamonds %>%
select(carat, color, price) %>%
mutate(price_twd = price*30) %>%
filter(price_twd >= 10000) %>%
group_by(color) %>%
summarise(price_twd = mean(price_twd), carat = mean(carat)) %>%
arrange(color) %>%
slice(2:6) %>%
mutate(p_per_c = price_twd/carat) %>%
arrange(desc(p_per_c))
#> # A tibble: 5 × 4
#> color price_twd carat p_per_c
#> <ord> <dbl> <dbl> <dbl>
#> 1 G 119974. 0.771 155570.
#> 2 F 111747. 0.737 151719.
#> 3 I 152756. 1.03 148751.
#> 4 H 134600. 0.912 147620.
#> 5 E 92328. 0.658 140316.
%>% 的發音
在學校擔任助教的時候,曾有同學問過,要怎麼念出 %>%
?
查了之後才發現發音很多元,有人念 “then”,有人念 “pipe”,以前我都念「趴大於趴」,但其實沒有任何限制,要怎麼念都可以。
如果你對其他 R 語言中符號的發音有興趣,可以參考這篇討論。 趴趴熊非常可愛!
小結
我在這篇文中,介紹了 %>%
管線運算子的意義,還有派上用場的時機。之後的文章會繼續介紹 R語言當中的符號、函數以及套件,希望你喜歡這篇文章。
No Comments