Trong mỗi chúng ta đều có một thiên tài đang ngủ, chỉ có điều càng ngày anh ta ngủ càng say
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()
Giới thiệu
Nhanh quá! purrr cũng không có quá nhiều thứ để học nhưng mà càng học càng sợ nhanh hết, mà quan trọng hơn càng đọc càng thấy hay
Trong phần này tiếp tục giới thiệu 1 số tiện ích của purrr
invoke_map()
Cú pháp:
invoke_map(.f, .x = list(NULL), …, .env = NULL)
Lấy ý tưởng từ hàm do.call nhưng được viết lại dễ sử dụng hơn với pipe. invoke_map() làm việc với 1 list các hàm (invoke chỉ làm với 1 hàm)
Ví dụ:
- Với nhiều hàm có cùng object như nhau (đều có đầu vào là n)
invoke_map(list(runif, rnorm), n = 5)
## [[1]]
## [1] 0.5840509 0.3287739 0.7719973 0.8382072 0.4159901
##
## [[2]]
## [1] -0.3270957 -1.9810410 0.2708896 0.9089078 0.5063823
- Với 1 hàm list argument đầu tiên
set.seed(158)
invoke_map("runif", list(5, 10)) # invoke_map("runif", list(list(n = 5), list(n = 10)))
## [[1]]
## [1] 0.7971946 0.9885000 0.6124226 0.4691508 0.3604160
##
## [[2]]
## [1] 0.4601691 0.1228639 0.7343001 0.6868546 0.5806192 0.1728769 0.9669770
## [8] 0.5230550 0.5934103 0.4695439
- Nhiều hàm, nhiều agrument khác nhau
f <- c("runif", "rnorm", "rpois")
param <- list(
list(min = -1, max = 1),
list(sd = 5),
list(lambda = 10)
)
invoke_map(f, param, n = 5) %>% str()
## List of 3
## $ : num [1:5] -0.0692 -0.8097 -0.2257 -0.8307 0.7163
## $ : num [1:5] 1.1 -3.71 -9.87 5.63 -1.95
## $ : int [1:5] 9 8 6 11 24
list(m1 = mean, m2 = median) %>% invoke_map(x = rcauchy(100))
## $m1
## [1] -0.3312988
##
## $m2
## [1] 0.1682701
pwalk()
Hàm pwalk() tương tự như các hàm map nhưng không trả về giá trị, chỉ thực hiện hàm
plots <- mtcars %>%
split(.$cyl) %>%
map(~ggplot(., aes(mpg, wt)) + geom_point())
paths <- stringr::str_c(names(plots), ".pdf")
pwalk(list(paths, plots), ggsave, path = tempdir())
## Saving 7 x 5 in image
## Saving 7 x 5 in image
## Saving 7 x 5 in image
keep() và discard()
là 1 dạng loop như map, giữ hoặc loại bỏ phần tử nếu thỏa điều kiện
iris %>% keep(is.factor) %>% str()
## 'data.frame': 150 obs. of 1 variable:
## $ Species: Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
iris %>% discard(is.factor) %>% str()
## 'data.frame': 150 obs. of 4 variables:
## $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
## $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
## $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
## $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
rep(10, 10) %>%
map(sample, 5) %>%
keep(~ mean(.x) > 6)
## [[1]]
## [1] 4 10 9 8 6
##
## [[2]]
## [1] 10 8 6 7 1
##
## [[3]]
## [1] 2 7 8 6 10
##
## [[4]]
## [1] 5 8 4 7 10
some() và every()
Kiểm tra tất cả các phần tử với cùng 1 điều kiện
x <- list(1:5, letters, list(10))
x %>% some(is_character)
## [1] TRUE
x %>% every(is_vector)
## [1] TRUE
detect() và dectect_index()
x <- sample(10)
x
## [1] 8 5 10 3 1 4 7 9 2 6
x %>% detect(~ . > 5)
## [1] 8
x %>% detect_index(~ . > 5)
## [1] 1
reduce()
Đưa 1 list tương đối phức tạp về dạng đơn giản hơn bằng việc lặp lại hàm trong reduce với các phần tử của list
Ví dụ:
dfs <- list(
age = tibble(name = "John", age = 30),
sex = tibble(name = c("John", "Mary"), sex = c("M", "F")),
trt = tibble(name = "Mary", treatment = "A")
)
dfs %>% reduce(full_join)
## Joining, by = "name"
## Joining, by = "name"
## # A tibble: 2 x 4
## name age sex treatment
## <chr> <dbl> <chr> <chr>
## 1 John 30 M <NA>
## 2 Mary NA F A
vs <- list(
c(1, 3, 5, 6, 10),
c(1, 2, 3, 7, 8, 10),
c(1, 2, 3, 4, 8, 9, 10)
)
vs %>% reduce(intersect)
## [1] 1 3 10
accumulate()
Cho ra kết quả của từng bước reduce
x <- sample(10)
x %>% accumulate(`+`)
## [1] 7 12 22 25 33 39 43 45 54 55
x %>% reduce(`+`)
## [1] 55
LS0tCnRpdGxlOiAiSMaw4bubbmcgZOG6q24gc+G7rSBk4bulbmcgcHVycnIgcGFja2FnZSBwYXJ0IDQiCmF1dGhvcjogIk5ndXnhu4VuIE5n4buNYyBCw6xuaCIKZGF0ZTogIjE0IEFwciAyMDE5IgpvdXRwdXQ6CiAgIGh0bWxfZG9jdW1lbnQ6IAogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgIyBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogImRlZmF1bHQiCiAgICB0b2M6IFRSVUUKICAgIHRvY19mbG9hdDogVFJVRQogICAgZGV2OiAnc3ZnJwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCgpgYGAKCj4gVHJvbmcgbeG7l2kgY2jDum5nIHRhIMSR4buBdSBjw7MgbeG7mXQgdGhpw6puIHTDoGkgxJFhbmcgbmfhu6csIGNo4buJIGPDsyDEkWnhu4F1IGPDoG5nIG5nw6B5IGFuaCB0YSBuZ+G7pyBjw6BuZyBzYXkKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgoKCiMgR2nhu5tpIHRoaeG7h3UKCk5oYW5oIHF1w6EhIHB1cnJyIGPFqW5nIGtow7RuZyBjw7MgcXXDoSBuaGnhu4F1IHRo4bupIMSR4buDIGjhu41jIG5oxrBuZyBtw6AgY8OgbmcgaOG7jWMgY8Ogbmcgc+G7oyBuaGFuaCBo4bq/dCwgbcOgIHF1YW4gdHLhu41uZyBoxqFuIGPDoG5nIMSR4buNYyBjw6BuZyB0aOG6pXkgaGF5CgpUcm9uZyBwaOG6p24gbsOgeSB0aeG6v3AgdOG7pWMgZ2nhu5tpIHRoaeG7h3UgMSBz4buRIHRp4buHbiDDrWNoIGPhu6dhIHB1cnJyCgojIGludm9rZV9tYXAoKQoKQ8O6IHBow6FwOgoKPiBpbnZva2VfbWFwKC5mLCAueCA9IGxpc3QoTlVMTCksIC4uLiwgLmVudiA9IE5VTEwpCgpM4bqleSDDvSB0xrDhu59uZyB04burIGjDoG0gZG8uY2FsbCBuaMawbmcgxJHGsOG7o2Mgdmnhur90IGzhuqFpIGThu4Ugc+G7rSBk4bulbmcgaMahbiB24bubaSBwaXBlLiBpbnZva2VfbWFwKCkgbMOgbSB2aeG7h2MgduG7m2kgMSBsaXN0IGPDoWMgaMOgbSAoaW52b2tlIGNo4buJIGzDoG0gduG7m2kgMSBow6BtKQoKVsOtIGThu6U6CgotIFbhu5tpIG5oaeG7gXUgaMOgbSBjw7MgY8O5bmcgb2JqZWN0IG5oxrAgbmhhdSAoxJHhu4F1IGPDsyDEkeG6p3UgdsOgbyBsw6AgbikKYGBge3J9Cmludm9rZV9tYXAobGlzdChydW5pZiwgcm5vcm0pLCBuID0gNSkKYGBgCgotIFbhu5tpIDEgaMOgbSBsaXN0IGFyZ3VtZW50IMSR4bqndSB0acOqbgpgYGB7cn0Kc2V0LnNlZWQoMTU4KQppbnZva2VfbWFwKCJydW5pZiIsIGxpc3QoNSwgMTApKSAjIGludm9rZV9tYXAoInJ1bmlmIiwgbGlzdChsaXN0KG4gPSA1KSwgbGlzdChuID0gMTApKSkKYGBgCgotIE5oaeG7gXUgaMOgbSwgbmhp4buBdSBhZ3J1bWVudCBraMOhYyBuaGF1CmBgYHtyfQpmIDwtIGMoInJ1bmlmIiwgInJub3JtIiwgInJwb2lzIikKcGFyYW0gPC0gbGlzdCgKICAgIGxpc3QobWluID0gLTEsIG1heCA9IDEpLAogICAgbGlzdChzZCA9IDUpLAogICAgbGlzdChsYW1iZGEgPSAxMCkKKQoKaW52b2tlX21hcChmLCBwYXJhbSwgbiA9IDUpICU+JSBzdHIoKQpgYGAKCi0gU+G7rSBk4bulbmcgduG7m2kgdG/DoW4gdOG7rSBwaXBlCmBgYHtyfQpsaXN0KG0xID0gbWVhbiwgbTIgPSBtZWRpYW4pICU+JSBpbnZva2VfbWFwKHggPSByY2F1Y2h5KDEwMCkpCmBgYAoKCiMgcHdhbGsoKQoKSMOgbSBwd2FsaygpIHTGsMahbmcgdOG7sSBuaMawIGPDoWMgaMOgbSBtYXAgbmjGsG5nIGtow7RuZyB0cuG6oyB24buBIGdpw6EgdHLhu4ssIGNo4buJIHRo4buxYyBoaeG7h24gaMOgbQoKYGBge3J9CnBsb3RzIDwtIG10Y2FycyAlPiUKICBzcGxpdCguJGN5bCkgJT4lCiAgbWFwKH5nZ3Bsb3QoLiwgYWVzKG1wZywgd3QpKSArIGdlb21fcG9pbnQoKSkKCnBhdGhzIDwtIHN0cmluZ3I6OnN0cl9jKG5hbWVzKHBsb3RzKSwgIi5wZGYiKQoKcHdhbGsobGlzdChwYXRocywgcGxvdHMpLCBnZ3NhdmUsIHBhdGggPSB0ZW1wZGlyKCkpCmBgYAoKCiMga2VlcCgpIHbDoCBkaXNjYXJkKCkKCmzDoCAxIGThuqFuZyBsb29wIG5oxrAgbWFwLCBnaeG7ryBob+G6t2MgbG/huqFpIGLhu48gcGjhuqduIHThu60gbuG6v3UgdGjhu49hIMSRaeG7gXUga2nhu4duCgpgYGB7cn0KaXJpcyAlPiUga2VlcChpcy5mYWN0b3IpICU+JSBzdHIoKQpgYGAKCmBgYHtyfQppcmlzICU+JSBkaXNjYXJkKGlzLmZhY3RvcikgJT4lIHN0cigpCmBgYAoKYGBge3J9CnJlcCgxMCwgMTApICU+JQogIG1hcChzYW1wbGUsIDUpICU+JQogIGtlZXAofiBtZWFuKC54KSA+IDYpCmBgYAoKIyBzb21lKCkgdsOgIGV2ZXJ5KCkKCktp4buDbSB0cmEgdOG6pXQgY+G6oyBjw6FjIHBo4bqnbiB04butIHbhu5tpIGPDuW5nIDEgxJFp4buBdSBraeG7h24KCmBgYHtyfQp4IDwtIGxpc3QoMTo1LCBsZXR0ZXJzLCBsaXN0KDEwKSkKeCAlPiUgc29tZShpc19jaGFyYWN0ZXIpCgp4ICU+JSBldmVyeShpc192ZWN0b3IpCmBgYAoKIyBkZXRlY3QoKSB2w6AgZGVjdGVjdF9pbmRleCgpCmBgYHtyfQp4IDwtIHNhbXBsZSgxMCkKeAoKeCAlPiUgZGV0ZWN0KH4gLiA+IDUpCgp4ICU+JSBkZXRlY3RfaW5kZXgofiAuID4gNSkKYGBgCgoKIyByZWR1Y2UoKQoKxJDGsGEgMSBsaXN0IHTGsMahbmcgxJHhu5FpIHBo4bupYyB04bqhcCB24buBIGThuqFuZyDEkcahbiBnaeG6o24gaMahbiBi4bqxbmcgdmnhu4djIGzhurdwIGzhuqFpIGjDoG0gdHJvbmcgcmVkdWNlIHbhu5tpIGPDoWMgcGjhuqduIHThu60gY+G7p2EgbGlzdAoKVsOtIGThu6U6CgpgYGB7cn0KZGZzIDwtIGxpc3QoCmFnZSA9IHRpYmJsZShuYW1lID0gIkpvaG4iLCBhZ2UgPSAzMCksCnNleCA9IHRpYmJsZShuYW1lID0gYygiSm9obiIsICJNYXJ5IiksIHNleCA9IGMoIk0iLCAiRiIpKSwKdHJ0ID0gdGliYmxlKG5hbWUgPSAiTWFyeSIsIHRyZWF0bWVudCA9ICJBIikKKQoKZGZzICU+JSByZWR1Y2UoZnVsbF9qb2luKQpgYGAKCmBgYHtyfQp2cyA8LSBsaXN0KApjKDEsIDMsIDUsIDYsIDEwKSwKYygxLCAyLCAzLCA3LCA4LCAxMCksCmMoMSwgMiwgMywgNCwgOCwgOSwgMTApCikKdnMgJT4lIHJlZHVjZShpbnRlcnNlY3QpCmBgYAoKIyBhY2N1bXVsYXRlKCkKCkNobyByYSBr4bq/dCBxdeG6oyBj4bunYSB04burbmcgYsaw4bubYyByZWR1Y2UKCmBgYHtyfQp4IDwtIHNhbXBsZSgxMCkKCnggJT4lIGFjY3VtdWxhdGUoYCtgKQp4ICU+JSByZWR1Y2UoYCtgKQpgYGAKCg==