Đời sống của người đàn ông là Danh; đời sống của người đàn bà là Tình
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)
Giới thiệu
Package purrr là 1 package rất mạnh, thiết kế rất thông minh, làm cho việc viết code trở lên đơn giản, dễ hiểu.
Trong phần này tôi sẽ giới thiệu các hàm map_*().
Các hàm họ map_* sử dụng cho vòng lặp (loop). Được thiết kế rất tiện và loại bỏ những thao tác thừa đối với việc sử dụng vòng lặp for, và đầu ra xác định rõ ràng hơn so với vòng lặp while. Cụ thể như sau:
Đối với vòng lặp for ta phải xác định trước số phần tử của object (nếu không muốn giảm hiệu năng của hàm). Còn đối với hàm map thì không cần làm công việc như vậy mà không bị ảnh hướng tới hiệu năng.
Thiết kế phù hợp để thực hiện theo chu trình (pipe %>%)
Đầu ra tiện ích hơn so với họ hàm apply, loại vector đầu ra được xác định dựa vào hậu tố của hàm
Thiết kế chung của họ hàm map
- map() makes a list.
- map_lgl() makes a logical vector.
- map_int() makes an integer vector.
- map_dbl() makes a double vector.
- map_chr() makes a character vector.
Một số ví dụ đối với hàm map_*()
map_dbl(airquality, mean)
## Ozone Solar.R Wind Temp Month Day
## NA NA 9.957516 77.882353 6.993464 15.803922
airquality %>% map_int(length)
## Ozone Solar.R Wind Temp Month Day
## 153 153 153 153 153 153
- Sử dụng … (“Dot-Dot-Dot (…)”
airquality %>% map_dbl(mean, trim = 0.5)
## Ozone Solar.R Wind Temp Month Day
## NA NA 9.7 79.0 7.0 16.0
- Sử dụng hàm ẩn (anonymous function)
Nếu viết dạng đầy đủ
models <- mtcars %>%
split(.$cyl) %>%
map(function(df) lm(mpg ~ wt, data = df))
Viết dạng hàm ẩn (ngắn gọn hơn)
models <- mtcars %>%
split(.$cyl) %>%
map(~lm(mpg ~ wt, data = .))
Chú ý: “.” thay cho object đã tạo ra trước đó (pronoun)
- Tính r.squared của các mô hình:
Dạng đầy đủ
models %>%
map(summary) %>%
map_dbl(~.$r.squared)
## 4 6 8
## 0.5086326 0.4645102 0.4229655
Hay ngắn gọn hơn khi trích tên của object (extracting named components)
models %>%
map(summary) %>%
map_dbl("r.squared")
## 4 6 8
## 0.5086326 0.4645102 0.4229655
Một số ví dụ đối với hàm pmap_* () và map2_*()
Cú pháp của hàm
map2(.x, .y, .f, …)
pmap(.l, .f, …)
Thay vì vòng lặp đối với 1 vector (1 agrument) như hàm map thì hàm map2_() và pmap_() tạo vòng lặp với 2 hay nhiều agrument
mu1 <- c(5, 10, 12)
sigma1 <- c(2, 4, 5)
map2(mu1, sigma1, rnorm, n = 5) %>% str()
## List of 3
## $ : num [1:5] 3.98 6.7 3.64 5.62 3.46
## $ : num [1:5] 8.98 12.1 14.25 10.56 8.6
## $ : num [1:5] 14.16 12.24 11.18 6.19 13.4
rnorm(n, mean, sd)
TH1: Thêm list n1 vào vòng lặp
n1 <- list(1, 3, 5)
args1 <- list(n1, mu1, sigma1) # Nếu tên khác agrument thì phải sắp xếp đúng thứ tự
set.seed(158)
args1 %>%
pmap(rnorm) %>%
str()
## List of 3
## $ : num 6.66
## $ : num [1:3] 11.14 8.57 5.36
## $ : num [1:5] 14.43 7.29 12.29 11.62 5.45
- Thêm vector n2 vào vòng lặp (thay đổi 1 chút thứ tự các agrument)
n2 <- c(1, 3, 5)
args2 <- list(mean = mu1, sd = sigma1, n = n2)
set.seed(158)
args2 %>%
pmap(rnorm) %>%
str()
## List of 3
## $ : num 6.66
## $ : num [1:3] 11.14 8.57 5.36
## $ : num [1:5] 14.43 7.29 12.29 11.62 5.45
set.seed(158)
params <- data.frame(mean = mu1, sd = sigma1, n = n2)
params %>%
pmap(rnorm) %>%
str()
## List of 3
## $ : num 6.66
## $ : num [1:3] 11.14 8.57 5.36
## $ : num [1:5] 14.43 7.29 12.29 11.62 5.45
Chú ý:
- Hàm pmap lặp theo thứ tự phần tử không phân biệt là list() hoặc vector c() hay data.frame.
- Nếu đầu vào đúng tên với agrument trong hàm thì không phân biệt việc sắp xếp agrument nào trước, agrument nào sau
LS0tCnRpdGxlOiAiSMaw4bubbmcgZOG6q24gc+G7rSBk4bulbmcgcHVycnIgcGFja2FnZSAocGFydCAxKSIKYXV0aG9yOiAiTmd1eeG7hW4gTmfhu41jIELDrG5oIgpkYXRlOiAiMiBBcHIgMjAxOSIKb3V0cHV0OgogICBodG1sX2RvY3VtZW50OiAKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgICNjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogImRlZmF1bHQiCiAgICB0b2M6IFRSVUUKICAgIHRvY19mbG9hdDogVFJVRQogICAgZGV2OiAnc3ZnJwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCgpgYGAKCj4gxJDhu51pIHPhu5FuZyBj4bunYSBuZ8aw4budaSDEkcOgbiDDtG5nIGzDoCBEYW5oOyDEkeG7nWkgc+G7kW5nIGPhu6dhIG5nxrDhu51pIMSRw6BuIGLDoCBsw6AgVMOsbmgKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShicm9vbSkKYGBgCgoKIyBHaeG7m2kgdGhp4buHdQoKUGFja2FnZSAqKnB1cnJyKiogbMOgIDEgcGFja2FnZSBy4bqldCBt4bqhbmgsIHRoaeG6v3Qga+G6vyBy4bqldCB0aMO0bmcgbWluaCwgbMOgbSBjaG8gdmnhu4djIHZp4bq/dCBjb2RlIHRy4bufIGzDqm4gxJHGoW4gZ2nhuqNuLCBk4buFIGhp4buDdS4KClRyb25nIHBo4bqnbiBuw6B5IHTDtGkgc+G6vSBnaeG7m2kgdGhp4buHdSBjw6FjIGjDoG0gbWFwXyooKS4gCgpDw6FjIGjDoG0gaOG7jSBtYXBfKiBz4butIGThu6VuZyBjaG8gdsOybmcgbOG6t3AgKGxvb3ApLiDEkMaw4bujYyB0aGnhur90IGvhur8gcuG6pXQgdGnhu4duIHbDoCBsb+G6oWkgYuG7jyBuaOG7r25nIHRoYW8gdMOhYyB0aOG7q2EgxJHhu5FpIHbhu5tpIHZp4buHYyBz4butIGThu6VuZyB2w7JuZyBs4bq3cCBmb3IsIHbDoCDEkeG6p3UgcmEgeMOhYyDEkeG7i25oIHLDtSByw6BuZyBoxqFuIHNvIHbhu5tpIHbDsm5nIGzhurdwIHdoaWxlLiBD4bulIHRo4buDIG5oxrAgc2F1OgoKLSDEkOG7kWkgduG7m2kgdsOybmcgbOG6t3AgZm9yIHRhIHBo4bqjaSB4w6FjIMSR4buLbmggdHLGsOG7m2Mgc+G7kSBwaOG6p24gdOG7rSBj4bunYSBvYmplY3QgKG7hur91IGtow7RuZyBtdeG7kW4gZ2nhuqNtIGhp4buHdSBuxINuZyBj4bunYSBow6BtKS4gQ8OybiDEkeG7kWkgduG7m2kgaMOgbSBtYXAgdGjDrCBraMO0bmcgY+G6p24gbMOgbSBjw7RuZyB2aeG7h2MgbmjGsCB24bqteSBtw6Aga2jDtG5nIGLhu4sg4bqjbmggaMaw4bubbmcgdOG7m2kgaGnhu4d1IG7Eg25nLiAKCi0gVGhp4bq/dCBr4bq/IHBow7kgaOG7o3AgxJHhu4MgdGjhu7FjIGhp4buHbiB0aGVvIGNodSB0csOsbmggKHBpcGUgJT4lKQoKLSDEkOG6p3UgcmEgdGnhu4duIMOtY2ggaMahbiBzbyB24bubaSBo4buNIGjDoG0gYXBwbHksIGxv4bqhaSB2ZWN0b3IgxJHhuqd1IHJhIMSRxrDhu6NjIHjDoWMgxJHhu4tuaCBk4buxYSB2w6BvIGjhuq11IHThu5EgY+G7p2EgaMOgbSAKCiMgVGhp4bq/dCBr4bq/IGNodW5nIGPhu6dhIGjhu40gaMOgbSBtYXAKCiogbWFwKCkgbWFrZXMgYSBsaXN0LgoqIG1hcF9sZ2woKSBtYWtlcyBhIGxvZ2ljYWwgdmVjdG9yLgoqIG1hcF9pbnQoKSBtYWtlcyBhbiBpbnRlZ2VyIHZlY3Rvci4KKiBtYXBfZGJsKCkgbWFrZXMgYSBkb3VibGUgdmVjdG9yLgoqIG1hcF9jaHIoKSBtYWtlcyBhIGNoYXJhY3RlciB2ZWN0b3IuCgojIE3hu5l0IHPhu5EgdsOtIGThu6UgxJHhu5FpIHbhu5tpIGjDoG0gbWFwXyooKQoKLSBUw61uaCB0cnVuZyBiw6xuaAoKYGBge3J9Cm1hcF9kYmwoYWlycXVhbGl0eSwgbWVhbikKYGBgCgotIFPhu60gZOG7pW5nIHbhu5tpIHRvw6FuIHThu60gcGlwZQoKYGBge3J9CmFpcnF1YWxpdHkgJT4lIG1hcF9pbnQobGVuZ3RoKQpgYGAKCi0gU+G7rSBk4bulbmcgLi4uICjigJxEb3QtRG90LURvdCAo4oCmKeKAnQoKYGBge3J9CmFpcnF1YWxpdHkgJT4lIG1hcF9kYmwobWVhbiwgdHJpbSA9IDAuNSkKYGBgCgotIFPhu60gZOG7pW5nIGjDoG0g4bqpbiAoYW5vbnltb3VzIGZ1bmN0aW9uKSAKCk7hur91IHZp4bq/dCBk4bqhbmcgxJHhuqd5IMSR4bunCgpgYGB7cn0KbW9kZWxzIDwtIG10Y2FycyAlPiUKICAgIHNwbGl0KC4kY3lsKSAlPiUKICAgIG1hcChmdW5jdGlvbihkZikgbG0obXBnIH4gd3QsIGRhdGEgPSBkZikpCmBgYAoKVmnhur90IGThuqFuZyBow6BtIOG6qW4gKG5n4bqvbiBn4buNbiBoxqFuKQoKYGBge3J9Cm1vZGVscyA8LSBtdGNhcnMgJT4lCiAgICBzcGxpdCguJGN5bCkgJT4lCiAgICBtYXAofmxtKG1wZyB+IHd0LCBkYXRhID0gLikpCmBgYAoKQ2jDuiDDvTogIi4iIHRoYXkgY2hvIG9iamVjdCDEkcOjIHThuqFvIHJhIHRyxrDhu5tjIMSRw7MgKHByb25vdW4pCgotIFTDrW5oIHIuc3F1YXJlZCBj4bunYSBjw6FjIG3DtCBow6xuaDoKCkThuqFuZyDEkeG6p3kgxJHhu6cKYGBge3J9Cm1vZGVscyAlPiUKICAgIG1hcChzdW1tYXJ5KSAlPiUKICAgIG1hcF9kYmwofi4kci5zcXVhcmVkKQoKYGBgCgpIYXkgbmfhuq9uIGfhu41uIGjGoW4ga2hpIHRyw61jaCB0w6puIGPhu6dhIG9iamVjdCAoZXh0cmFjdGluZyBuYW1lZCBjb21wb25lbnRzKQoKYGBge3J9Cm1vZGVscyAlPiUKICAgIG1hcChzdW1tYXJ5KSAlPiUKICAgIG1hcF9kYmwoInIuc3F1YXJlZCIpCmBgYAoKIyBN4buZdCBz4buRIHbDrSBk4bulIMSR4buRaSB24bubaSBow6BtIHBtYXBfKiAoKSB2w6AgbWFwMl8qKCkKCkPDuiBwaMOhcCBj4bunYSBow6BtIAoKPiBtYXAyKC54LCAueSwgLmYsIC4uLikKCj4gcG1hcCgubCwgLmYsIC4uLikKClRoYXkgdsOsIHbDsm5nIGzhurdwIMSR4buRaSB24bubaSAxIHZlY3RvciAoMSBhZ3J1bWVudCkgbmjGsCBow6BtIG1hcCB0aMOsIGjDoG0gbWFwMl8oKSB2w6AgcG1hcF8oKSB04bqhbyB2w7JuZyBs4bq3cCB24bubaSAyIGhheSBuaGnhu4F1IGFncnVtZW50CgotIFbDrSBk4bulIHbhu5tpIG1hcDIKCmBgYHtyfQptdTEgPC0gYyg1LCAxMCwgMTIpCnNpZ21hMSA8LSBjKDIsIDQsIDUpCgptYXAyKG11MSwgc2lnbWExLCBybm9ybSwgbiA9IDUpICU+JSBzdHIoKQoKYGBgCgotIFbDrSBk4bulIHbhu5tpIHBtYXAKCj4gcm5vcm0obiwgbWVhbiwgc2QpCgpUSDE6IFRow6ptIGxpc3QgbjEgdsOgbyB2w7JuZyBs4bq3cAoKYGBge3J9Cm4xIDwtIGxpc3QoMSwgMywgNSkKYXJnczEgPC0gbGlzdChuMSwgbXUxLCBzaWdtYTEpICMgTuG6v3UgdMOqbiBraMOhYyBhZ3J1bWVudCB0aMOsIHBo4bqjaSBz4bqvcCB44bq/cCDEkcO6bmcgdGjhu6kgdOG7sQpzZXQuc2VlZCgxNTgpCmFyZ3MxICU+JQogICAgcG1hcChybm9ybSkgJT4lCiAgICBzdHIoKQpgYGAKCi0gVGjDqm0gdmVjdG9yIG4yIHbDoG8gdsOybmcgbOG6t3AgKHRoYXkgxJHhu5VpIDEgY2jDunQgdGjhu6kgdOG7sSBjw6FjIGFncnVtZW50KQpgYGB7cn0KbjIgPC0gYygxLCAzLCA1KQphcmdzMiA8LSBsaXN0KG1lYW4gPSBtdTEsIHNkID0gc2lnbWExLCBuID0gbjIpCnNldC5zZWVkKDE1OCkKYXJnczIgJT4lCiAgICBwbWFwKHJub3JtKSAlPiUKICAgIHN0cigpCmBgYAoKLSBWw7JuZyBs4bq3cCB24bubaSBkYXRhLmZyYW1lCmBgYHtyfQpzZXQuc2VlZCgxNTgpCnBhcmFtcyA8LSBkYXRhLmZyYW1lKG1lYW4gPSBtdTEsIHNkID0gc2lnbWExLCBuID0gbjIpCnBhcmFtcyAlPiUKICAgIHBtYXAocm5vcm0pICU+JQogICAgc3RyKCkKYGBgCgpDaMO6IMO9OiAKCi0gSMOgbSAqKnBtYXAqKiBs4bq3cCB0aGVvIHRo4bupIHThu7EgcGjhuqduIHThu60ga2jDtG5nIHBow6JuIGJp4buHdCBsw6AgbGlzdCgpIGhv4bq3YyB2ZWN0b3IgYygpIGhheSBkYXRhLmZyYW1lLiAKLSBO4bq/dSDEkeG6p3UgdsOgbyDEkcO6bmcgdMOqbiB24bubaSBhZ3J1bWVudCB0cm9uZyBow6BtIHRow6wga2jDtG5nIHBow6JuIGJp4buHdCB2aeG7h2Mgc+G6r3AgeOG6v3AgYWdydW1lbnQgbsOgbyB0csaw4bubYywgYWdydW1lbnQgbsOgbyBzYXUKCg==