Bạn sẽ nhận ra những giây phút nào là quan trọng nhất trong cuộc đời khi mà mọi chuyện đã muộn

library(tidyverse)
## ── Attaching packages ────────────────────────────────────────────────────── tidyverse 1.2.1 ──
## ✔ ggplot2 3.1.1       ✔ purrr   0.3.2  
## ✔ tibble  2.1.1       ✔ dplyr   0.8.0.1
## ✔ tidyr   0.8.3       ✔ stringr 1.4.0  
## ✔ readr   1.3.1       ✔ forcats 0.4.0
## ── Conflicts ───────────────────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
library(broom)

1 Giới thiệu

Hầu hết mọi người sử dụng package purrr thường chủ yếu tập trung vào các tính năng của hàm map_* mà quên đi nhiều tiện ích của purrr

Tận dụng các tiện ích của package purrr làm cho công việc viết code đơn giản như việc thưởng thức tách cafe, và hơn nữa code cũng sáng sủa, rõ ràng hơn

Thi thoảng thay đổi cách viết code cùng làm cho công việc bớt nhàm chán hơn

Trong phần này tôi sẽ giới thiệu 2 hàm compose và partial

2 compose()

Đầu tiên tôi ví dụ 1 đoạn code:

lm(Sepal.Length ~ Species, data = iris) %>% tidy() %>% filter(p.value < 0.05)
lm(Pepal.Length ~ Species, data = iris) %>% tidy() %>% filter(p.value < 0.05)
lm(Sepal.Width ~ Species, data = iris) %>% tidy() %>% filter(p.value < 0.05)
lm(Sepal.Length ~ Species, data = iris) %>% tidy() %>% ilter(p.value < 0.05)

Nếu chúng ta viết code như trên thông thường mắt của chúng ta sẽ chỉ tập trung vào những điểm giống nhau thay vì tập trung vào những điểm thay đổi của các dòng code. Vì vậy, coder rất dễ mắc lỗi khi viết nhiều dòng tương tự nhau. Chú ý rằng nếu code lặp lại trên 2 lần thì nên sử dụng function. Với purrr thay vì viết hàm mới thì chúng ta nên modify hoặc kết hợp các hàm lại với nhau

So sánh 2 cách viết

tidy(lm(Sepal.Length ~ Species, data = iris))
## # A tibble: 3 x 5
##   term              estimate std.error statistic   p.value
##   <chr>                <dbl>     <dbl>     <dbl>     <dbl>
## 1 (Intercept)           5.01    0.0728     68.8  1.13e-113
## 2 Speciesversicolor     0.93    0.103       9.03 8.77e- 16
## 3 Speciesvirginica      1.58    0.103      15.4  2.21e- 32

và cách 2 sử dụng hàm compose

tidy_lm <- compose(tidy, lm)
tidy_lm(Sepal.Length ~ Species, data = iris)
## # A tibble: 3 x 5
##   term              estimate std.error statistic   p.value
##   <chr>                <dbl>     <dbl>     <dbl>     <dbl>
## 1 (Intercept)           5.01    0.0728     68.8  1.13e-113
## 2 Speciesversicolor     0.93    0.103       9.03 8.77e- 16
## 3 Speciesvirginica      1.58    0.103      15.4  2.21e- 32

Như vậy, bằng cách kết hợp hàm lmtidy (theo nguyên tắc từ phải sang trái) chúng ta có hàm tidy_lm ngắn gọn

Sử dụng as_mapper để convert 1 object sang function và cũng sử dụng hàm compose

clean_lm <- compose(as_mapper(~ arrange(.x, desc(p.value))), 
                    as_mapper(~ filter(.x, p.value < 0.05)),
                    tidy, 
                    lm)
clean_lm(Sepal.Length ~ Sepal.Width, data = iris)
## # A tibble: 1 x 5
##   term        estimate std.error statistic  p.value
##   <chr>          <dbl>     <dbl>     <dbl>    <dbl>
## 1 (Intercept)     6.53     0.479      13.6 6.47e-28

3 partial()

Cách viết thông thường khi tính giá trị trung bình với vector có giá trị NA

mean(airquality$Ozone, na.rm = TRUE)
## [1] 42.12931

Sử dụng hàm partial

mean_na_rm <- partial(mean, na.rm = TRUE)
mean_na_rm(airquality$Ozone)
## [1] 42.12931

kết quả tương tự đoạn code trên nhưng ngắn gọn hơn

Tham khảo: https://colinfay.me

LS0tCnRpdGxlOiAiSMaw4bubbmcgZOG6q24gc+G7rSBk4bulbmcgcHVycnIgcGFja2FnZSAocGFydCAyKSIKYXV0aG9yOiAiTmd1eeG7hW4gTmfhu41jIELDrG5oIgpkYXRlOiAiNSBBcHIgMjAxOSIKb3V0cHV0OgogICBodG1sX2RvY3VtZW50OiAKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgICNjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogImRlZmF1bHQiCiAgICB0b2M6IFRSVUUKICAgIHRvY19mbG9hdDogVFJVRQogICAgZGV2OiAnc3ZnJwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCgpgYGAKCj4gQuG6oW4gc+G6vSBuaOG6rW4gcmEgbmjhu69uZyBnacOieSBwaMO6dCBuw6BvIGzDoCBxdWFuIHRy4buNbmcgbmjhuqV0IHRyb25nIGN14buZYyDEkeG7nWkga2hpIG3DoCBt4buNaSBjaHV54buHbiDEkcOjIG114buZbgoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGJyb29tKQpgYGAKCgojIEdp4bubaSB0aGnhu4d1CgpI4bqndSBo4bq/dCBt4buNaSBuZ8aw4budaSBz4butIGThu6VuZyBwYWNrYWdlICoqcHVycnIqKiB0aMaw4budbmcgY2jhu6cgeeG6v3UgdOG6rXAgdHJ1bmcgdsOgbyBjw6FjIHTDrW5oIG7Eg25nIGPhu6dhIGjDoG0gbWFwXyogbcOgIHF1w6puIMSRaSBuaGnhu4F1IHRp4buHbiDDrWNoIGPhu6dhIHB1cnJyCgpU4bqtbiBk4bulbmcgY8OhYyB0aeG7h24gw61jaCBj4bunYSBwYWNrYWdlIHB1cnJyIGzDoG0gY2hvIGPDtG5nIHZp4buHYyB2aeG6v3QgY29kZSDEkcahbiBnaeG6o24gbmjGsCB2aeG7h2MgdGjGsOG7n25nIHRo4bupYyB0w6FjaCBjYWZlLCB2w6AgaMahbiBu4buvYSBjb2RlIGPFqW5nIHPDoW5nIHPhu6dhLCByw7UgcsOgbmcgaMahbgoKVGhpIHRob+G6o25nIHRoYXkgxJHhu5VpIGPDoWNoIHZp4bq/dCBjb2RlIGPDuW5nIGzDoG0gY2hvIGPDtG5nIHZp4buHYyBi4bubdCBuaMOgbSBjaMOhbiBoxqFuCgpUcm9uZyBwaOG6p24gbsOgeSB0w7RpIHPhur0gZ2nhu5tpIHRoaeG7h3UgMiBow6BtIGNvbXBvc2UgdsOgIHBhcnRpYWwgCgojIGNvbXBvc2UoKSAKCsSQ4bqndSB0acOqbiB0w7RpIHbDrSBk4bulIDEgxJFv4bqhbiBjb2RlOiAKCmBgYHtyLCBldmFsID0gRkFMU0V9CmxtKFNlcGFsLkxlbmd0aCB+IFNwZWNpZXMsIGRhdGEgPSBpcmlzKSAlPiUgdGlkeSgpICU+JSBmaWx0ZXIocC52YWx1ZSA8IDAuMDUpCmxtKFBlcGFsLkxlbmd0aCB+IFNwZWNpZXMsIGRhdGEgPSBpcmlzKSAlPiUgdGlkeSgpICU+JSBmaWx0ZXIocC52YWx1ZSA8IDAuMDUpCmxtKFNlcGFsLldpZHRoIH4gU3BlY2llcywgZGF0YSA9IGlyaXMpICU+JSB0aWR5KCkgJT4lIGZpbHRlcihwLnZhbHVlIDwgMC4wNSkKbG0oU2VwYWwuTGVuZ3RoIH4gU3BlY2llcywgZGF0YSA9IGlyaXMpICU+JSB0aWR5KCkgJT4lIGlsdGVyKHAudmFsdWUgPCAwLjA1KQoKYGBgCgpO4bq/dSBjaMO6bmcgdGEgdmnhur90IGNvZGUgbmjGsCB0csOqbiB0aMO0bmcgdGjGsOG7nW5nIG3huq90IGPhu6dhIGNow7puZyB0YSBz4bq9IGNo4buJIHThuq1wIHRydW5nIHbDoG8gbmjhu69uZyDEkWnhu4NtIGdp4buRbmcgbmhhdSB0aGF5IHbDrCB04bqtcCB0cnVuZyB2w6BvIG5o4buvbmcgxJFp4buDbSB0aGF5IMSR4buVaSBj4bunYSBjw6FjIGTDsm5nIGNvZGUuIFbDrCB24bqteSwgY29kZXIgcuG6pXQgZOG7hSBt4bqvYyBs4buXaSBraGkgdmnhur90IG5oaeG7gXUgZMOybmcgdMawxqFuZyB04buxIG5oYXUuICoqQ2jDuiDDvSBy4bqxbmcgbuG6v3UgY29kZSBs4bq3cCBs4bqhaSB0csOqbiAyIGzhuqduIHRow6wgbsOqbiBz4butIGThu6VuZyBmdW5jdGlvbioqLiBW4bubaSBwdXJyciB0aGF5IHbDrCB2aeG6v3QgaMOgbSBt4bubaSB0aMOsIGNow7puZyB0YSBuw6puIG1vZGlmeSBob+G6t2Mga+G6v3QgaOG7o3AgY8OhYyBow6BtIGzhuqFpIHbhu5tpIG5oYXUKClNvIHPDoW5oIDIgY8OhY2ggdmnhur90IAoKYGBge3J9CnRpZHkobG0oU2VwYWwuTGVuZ3RoIH4gU3BlY2llcywgZGF0YSA9IGlyaXMpKQpgYGAKCgp2w6AgY8OhY2ggMiBz4butIGThu6VuZyBow6BtICoqY29tcG9zZSoqIAoKYGBge3J9CnRpZHlfbG0gPC0gY29tcG9zZSh0aWR5LCBsbSkKdGlkeV9sbShTZXBhbC5MZW5ndGggfiBTcGVjaWVzLCBkYXRhID0gaXJpcykKYGBgCgpOaMawIHbhuq15LCBi4bqxbmcgY8OhY2gga+G6v3QgaOG7o3AgaMOgbSAqKmxtKiogdsOgICoqdGlkeSoqICgqKnRoZW8gbmd1ecOqbiB04bqvYyB04burIHBo4bqjaSBzYW5nIHRyw6FpKiopIGNow7puZyB0YSBjw7MgaMOgbSAqKnRpZHlfbG0qKiBuZ+G6r24gZ+G7jW4KClPhu60gZOG7pW5nICoqYXNfbWFwcGVyKiogxJHhu4MgY29udmVydCAxICpvYmplY3QqIHNhbmcgKmZ1bmN0aW9uKiB2w6AgY8Wpbmcgc+G7rSBk4bulbmcgaMOgbSBjb21wb3NlCgpgYGB7cn0KY2xlYW5fbG0gPC0gY29tcG9zZShhc19tYXBwZXIofiBhcnJhbmdlKC54LCBkZXNjKHAudmFsdWUpKSksIAogICAgICAgICAgICAgICAgICAgIGFzX21hcHBlcih+IGZpbHRlcigueCwgcC52YWx1ZSA8IDAuMDUpKSwKICAgICAgICAgICAgICAgICAgICB0aWR5LCAKICAgICAgICAgICAgICAgICAgICBsbSkKY2xlYW5fbG0oU2VwYWwuTGVuZ3RoIH4gU2VwYWwuV2lkdGgsIGRhdGEgPSBpcmlzKQpgYGAKCiMgcGFydGlhbCgpCgpDw6FjaCB2aeG6v3QgdGjDtG5nIHRoxrDhu51uZyBraGkgdMOtbmggZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCB24bubaSB2ZWN0b3IgY8OzIGdpw6EgdHLhu4sgTkEKCmBgYHtyfQptZWFuKGFpcnF1YWxpdHkkT3pvbmUsIG5hLnJtID0gVFJVRSkKYGBgCgpT4butIGThu6VuZyBow6BtIHBhcnRpYWwgCgpgYGB7cn0KbWVhbl9uYV9ybSA8LSBwYXJ0aWFsKG1lYW4sIG5hLnJtID0gVFJVRSkKbWVhbl9uYV9ybShhaXJxdWFsaXR5JE96b25lKQpgYGAKCmvhur90IHF14bqjIHTGsMahbmcgdOG7sSDEkW/huqFuIGNvZGUgdHLDqm4gbmjGsG5nIG5n4bqvbiBn4buNbiBoxqFuIAoKPiBUaGFtIGto4bqjbzogaHR0cHM6Ly9jb2xpbmZheS5tZQ==