第 46 章 tidyverse中的dot
本章介绍tidyverse的语法中经常遇到.
, 不同的场景,含义不同。因此很有必要弄清楚各自的含义。
46.1 每一行的 .
各自代表什么意思呢?
read_csv("./data/wages.csv") %>%
mutate(letter = str_extract(race, "(?<=h)(.)")) %>%
select(., -letter) %>%
mutate_at(vars(race), ~ as.factor(.)) %>%
mutate_at(vars(sex), ~ if_else(. == "male", 1, 0)) %>%
filter_if(~ is.numeric(.), all_vars(. != 0)) %>%
split(.$sex) %>%
map(~ lm(earn ~ ., data = .)) %>%
map_dfr(~ broom::tidy(.), .id = "sex")
回答之前,我们先介绍一些相关知识点
46.2 占位符
管道符号%>%
主要功能是传递参数。
y %>% f()
is equivalent tof(y)
y %>% f(x, .)
is equivalent tof(x, y)
z %>% f(x, y, arg = .)
is equivalent tof(x, y, arg = z)
我们经常这样写
## cyl disp hp
## Mazda RX4 6 160 110
## Mazda RX4 Wag 6 160 110
实际上,这里是有占位符的
## cyl disp hp
## Mazda RX4 6 160 110
## Mazda RX4 Wag 6 160 110
46.3 Lambda函数
.
出现在函数.f
的位置上, 就是 purrr 风格的Lambda函数~ fun(.)
,
## GEAR CARB
## Mazda RX4 4 4
## Mazda RX4 Wag 4 4
## Datsun 710 4 1
有时候程序员会将~toupper(.)
简写成 toupper
## GEAR CARB
## Mazda RX4 4 4
## Mazda RX4 Wag 4 4
## Datsun 710 4 1
46.4 正则表达式
words <- "the fattest cat."
words %>% str_replace_all("t.", "-")
## [1] "-e fa-es-ca-"
words %>% str_replace_all("t\\.", "-")
## [1] "the fattest ca-"
46.6 more placeholder
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 30 4.7 3.2 1.6 0.2 setosa
## 60 5.2 2.7 3.9 1.4 versicolor
## 90 5.5 2.5 4.0 1.3 versicolor
## 120 6.0 2.2 5.0 1.5 virginica
## 150 5.9 3.0 5.1 1.8 virginica
## [1] 1 10
46.7 当mutate遇到map
当dplyr::mutate
遇到purrr::map
,情况就复杂很多了。然而,这种情况,tidyverse比比皆是。我就多说几句吧
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species r_sum
## 1 5.1 3.5 1.4 0.2 setosa 10.2
## 2 4.9 3.0 1.4 0.2 setosa 9.5
## 3 4.7 3.2 1.3 0.2 setosa 9.4
这里mutate()
行,有两个.
, 实际这两个.
都是等待iris %>% head(3)
传来的data.frame
## # A tibble: 2 × 2
## mean sd
## <dbl> <dbl>
## 1 1 2
## 2 2 4
df %>%
dplyr::mutate(., rand = map(mean, ~ rnorm(5, .))) %>%
tidyr::unnest_wider(col = rand, names_sep = " ")
## # A tibble: 2 × 7
## mean sd `rand 1` `rand 2` `rand 3` `rand 4` `rand 5`
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 2 1.02 0.203 1.06 1.07 1.09
## 2 2 4 1.49 0.998 3.75 0.379 2.02
- 第一个
.
, 是df
- 第二个
.
, 是df
中的mean
df %>%
dplyr::mutate(rand = map2(mean, sd, ~ rnorm(5, .x, .y))) %>%
tidyr::unnest_wider(rand, names_sep = " ")
## # A tibble: 2 × 7
## mean sd `rand 1` `rand 2` `rand 3` `rand 4` `rand 5`
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 2 4.29 2.13 2.53 1.55 -0.994
## 2 2 4 0.626 -2.49 4.45 -4.13 6.08
-
mean
传给.x
-
sd
传给.y
再来一个变态的。(我们不一定要这样写,但我们尽可能的要明白它的意思。)
## # A tibble: 2 × 3
## a b sum
## <dbl> <dbl> <dbl>
## 1 1 10 11
## 2 2 11 13
46.8 Dot dot dot
commas <- function(...) {
stringr::str_c(..., collapse = ", ")
}
commas(letters[1:10])
## [1] "a, b, c, d, e, f, g, h, i, j"
46.9 Don’t confuse
注意:有些函数的参数前缀是 .
mutate_all(.tbl, .funs, ...)
mutate_if(.tbl, .predicate, .funs, ...)
mutate_at(.tbl, .vars, .funs, ..., .cols = NULL)
select_all(.tbl, .funs = list(), ...)
rename_all(.tbl, .funs = list(), ...)
46.11 回答问题
现在回答本章开始的问题
read_csv("./demo_data/wages.csv") %>%
dplyr::mutate(letter = str_extract(race, "(?<=h)(.)")) %>%
dplyr::select(., -letter) %>%
dplyr::mutate_at(vars(race), ~ as.factor(.)) %>%
dplyr::mutate_at(vars(sex), ~ if_else(. == "male", 1, 0)) %>%
dplyr::filter_if(~ is.numeric(.), all_vars(. != 0)) %>%
split(.$sex) %>%
purrr::map(~ lm(earn ~ ., data = .)) %>%
purrr::map_dfr(., ~ broom::tidy(.), .id = "sex")
## # A tibble: 8 × 6
## sex term estimate std.error statistic p.value
## <chr> <chr> <dbl> <dbl> <dbl> <dbl>
## 1 1 (Intercept) -121846. 37449. -3.25 1.21e- 3
## 2 1 height 977. 515. 1.90 5.84e- 2
## 3 1 sex NA NA NA NA
## 4 1 racehispanic 578. 7934. 0.0728 9.42e- 1
## 5 1 raceother -2035. 11514. -0.177 8.60e- 1
## 6 1 racewhite 12823. 5284. 2.43 1.56e- 2
## 7 1 ed 5234. 601. 8.71 4.30e-17
## 8 1 age 406. 95.5 4.25 2.52e- 5
- 第1行:路径中
.
代表当前位置,如果是..
表示上一级目录 - 第2行:正则表达式,代表任何字符
- 第3行:占位符,等待数据框的传入,也可以简写
select(-letter)
- 第4行: lambda函数,
~ as.factor(.)
也可以简写as.factor
,~
和(.)
要么都写,要么都不写 - 第5行:同上,lambda函数
- 第6行:第一个
.
代表lambda函数; 第二个.
也是lambda函数,但这里它是all_vars(expr)
中expr的一种特有写法,代表所有数值型变量,*行方向构成的向量,all_vars(. != 0)
函数返回TRUE或FALSE,从而帮助filter()
是否筛选该行 - 第7行:占位符,代表上面传来的数据框
- 第8行:回归模型
lm
中,第一个.
代表除因变量earn之外所有的变量,第二个.
占位符,留给上面的数据框 - 第9行:第一个
.
是占位符,代表上面传来的list,第二个.
lambda函数,依次对list的元素迭代处理,第二个.
是参数名,.id
是特有的一个符号。