Cách sử dụng các toán tử pipes trong R
Sự ra đời của các toán tử pipes
trong package magrittr
đã tạo ra những thay đổi lớn mang tính cách mạng cho ngôn ngữ R
. Biết cách sử dụng linh hoạt các toán tử này chính là chìa khóa để rút ngắn thời gian viết code
cũng như giúp cho code
dễ đọc và dễ bảo trì hơn.
Ở bài này tôi note
lại cách dùng của 4 toán tử pipes
cho bạn nào cần:
%>%
: Forward-pipe operator%<>%
: Compound assignment pipe-operator%T>%
: Tee Operator%$%
: Exposition pipe-operator
Mục đích của việc sử dụng các toán tử pipes
trong R:
Tránh gọi lồng các hàm
Giảm việc tạo và sử dụng các biến trung gian
Tổ chức tập hợp các câu lệnh thành một chuỗi thống nhất, dễ hiểu.
Nạp các thư viện cần thiết vào phiên làm việc của R
để thực hành:
library(tidyverse)
library(magrittr)
Chú ý
: Khi nạp gói tidyverse
thì pipe %>%
được nạp tự động, tuy nhiên để dùng các toán từ khác thì chúng ta cần nạp thêm cả gói magrittr
.
1. Toán tử %>%
(forward-pipe operator)
Đây là pipe
được sử dụng nhiều nhất trong R, hầu như mỗi công việc thực hiện trên R tôi đều sử dụng nó rất nhiều lần.
Nguyên lý của pipe %>%
: chuyển toàn bộ vế bên trái (có thể là kết quả của hàm đi trước) thành dữ liệu đầu vào cho hàm bên phải tạo thành một dòng chảy dữ liệu từ trái qua phải.
Ví dụ với tập dữ liệu diamonds
:
head(diamonds)
## # A tibble: 6 x 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.290 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
## 6 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48
diamonds %>%
filter(color == "I") %>%
group_by(cut) %>%
summarize(price = mean(price))
## # A tibble: 5 x 2
## cut price
## <ord> <dbl>
## 1 Fair 4685.
## 2 Good 5079.
## 3 Very Good 5256.
## 4 Premium 5946.
## 5 Ideal 4452.
Tương đương với cách truyền thống như sau:
diamonds_1 <- filter(diamonds, color == "I")
diamonds_2 <- group_by(diamonds_1, cut)
(diamonds_3 <- summarize(diamonds_2, price = mean(price)))
## # A tibble: 5 x 2
## cut price
## <ord> <dbl>
## 1 Fair 4685.
## 2 Good 5079.
## 3 Very Good 5256.
## 4 Premium 5946.
## 5 Ideal 4452.
2. Toán tử %<>%
(compound assignment pipe-operator)
Nguyên lý của pipe %<>%:
Thực hiện nhiệm vụ tương tự như với toán tử %>%
, tuy nhiên kết quả cuối cùng của dòng chảy dữ liệu được gán lại vào đối tượng ban đầu của dòng chảy.
Ví dụ:
diamonds %<>%
filter(color == "I") %>% select(carat, cut, color)
diamonds
## # A tibble: 5,422 x 3
## carat cut color
## <dbl> <ord> <ord>
## 1 0.290 Premium I
## 2 0.24 Very Good I
## 3 0.3 Ideal I
## 4 0.3 Good I
## 5 0.24 Premium I
## 6 0.33 Ideal I
## 7 0.33 Ideal I
## 8 0.32 Ideal I
## 9 0.3 Ideal I
## 10 0.3 Very Good I
## # ... with 5,412 more rows
3. Toán tử %T%
(Tee Operator)
Nguyên lý của pipe %T>%
: Dòng chảy dữ liệu trong toán tử này có thể được hình dung tương tự như ống nước hình chữ T. Dữ liệu đầu vào của 1 hàm đi trước sẽ được truyền cho 2 nhánh tương ứng cho hai hàm phía sau
Ví dụ:
rnorm(200) %>%
matrix(ncol = 2) %T>%
plot %>%
colSums
## [1] -10.96542 -12.71731
Tương đương với:
rnorm(200) %>%
matrix(ncol = 2) %>%
{ plot(.); . } %>%
colSums
## [1] -10.652905 2.284913
Hoặc viết theo cách truyền thống:
m <- matrix(rnorm(200), ncol = 2)
plot(m)
colSums(m)
## [1] -27.205778 -2.992818
4. Toán tử %$%
(exposition pipe-operator)
Nguyên lý của pipe %$%
: Toán tử cho phép trích xuất đích danh một đối tượng trong kết quả của hàm đi trước để sử dụng như dữ liệu đầu vào cho hàm đi sau.
Ví dụ:
iris %>%
subset(Sepal.Length > mean(Sepal.Length)) %$%
cor(Sepal.Length, Sepal.Width)
## [1] 0.3361992
Tương đương với việc sử dụng hàm with():
with(subset(iris, Sepal.Length > mean(Sepal.Length)),
cor(Sepal.Length, Sepal.Width))
## [1] 0.3361992