概述
前置推文:dplyr | 数据导入和预处理的常用函数
前面介绍了dplyr
工具包中一些用于数据处理的常用函数,在处理的变量较少时,可以在相应的函数中逐个写入变量名,但当变量过多时,就需要寻求更加有效率的方式进行批量处理了。本篇介绍的colwise和rowwise操作就是一种对数据框更加省力的处理方式。
示例数据为mtcars
:
library(dplyr)
data <- mtcars
head(data)
## mpg cyl disp hp drat wt qsec vs am gear carb
## Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
## Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
## Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
## Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
## Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
1 colwise
colwise这个概念来自dplyr
工具包,其本身并不是一个函数,具体操作函数包括across
、if_any
和if_all
。
1.1 across
函数
across
函数的语法结构如下:
across(.cols = everything(), .fns = NULL, ...,
.names = NULL)
.cols:数据框中的变量名,默认为所有变量;
.fns:处理函数;
.names:处理后输出的变量名称。
.names
参数使用胶水函数对变量进行命名:
{.col}代表输入变量的列名,{.fn}代表处理函数名;
默认输出变量名同输入变量名,当有多个处理函数时,默认使用下划线加函数名进行命名。
该函数常用于分类汇总。比如要统计mtcars
中各变量的平均数,在不使用colwise操作的情况下,程序书写会很繁琐:
data %>%
group_by(cyl) %>%
summarise(v1 = mean(mpg),
v2 = mean(wt),
v3 = mean(qsec))
## # A tibble: 3 x 4
## cyl v1 v2 v3
## * <dbl> <dbl> <dbl> <dbl>
## 1 4 26.7 2.29 19.1
## 2 6 19.7 3.12 18.0
## 3 8 15.1 4.00 16.8
这里仅以三个变量为例。
使用colwise操作的程序如下:
data %>%
group_by(cyl) %>%
summarise(across(everything(), mean,
.names = "mean_{.col}"))
## # A tibble: 3 x 11
## cyl mean_mpg mean_disp mean_hp mean_drat mean_wt mean_qsec mean_vs mean_am
## * <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 4 26.7 105. 82.6 4.07 2.29 19.1 0.909 0.727
## 2 6 19.7 183. 122. 3.59 3.12 18.0 0.571 0.429
## 3 8 15.1 353. 209. 3.23 4.00 16.8 0 0.143
## # ... with 2 more variables: mean_gear <dbl>, mean_carb <dbl>
这里还使用了辅助函数everything
,表示选择所有变量。如果只针对个别变量,程序如下:
data %>%
group_by(cyl) %>%
summarise(across(c(mpg, disp, hp), mean,
.names = "mean_{.col}"))
## # A tibble: 3 x 4
## cyl mean_mpg mean_disp mean_hp
## * <dbl> <dbl> <dbl> <dbl>
## 1 4 26.7 105. 82.6
## 2 6 19.7 183. 122.
## 3 8 15.1 353. 209.
当变量的列序号是相连的时,还可以使用冒号:
进行简写:
data %>%
group_by(cyl) %>%
summarise(across(c(mpg:hp), mean,
.names = "mean_{.col}"))
## # A tibble: 3 x 4
## cyl mean_mpg mean_disp mean_hp
## * <dbl> <dbl> <dbl> <dbl>
## 1 4 26.7 105. 82.6
## 2 6 19.7 183. 122.
## 3 8 15.1 353. 209.
处理函数有多个时,使用list
函数储存相应的函数:
data %>%
group_by(cyl) %>%
summarise(across(c(mpg:hp), list(mean, var),
.names = "{.fn}_{.col}"))
## # A tibble: 3 x 7
## cyl `1_mpg` `2_mpg` `1_disp` `2_disp` `1_hp` `2_hp`
## * <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 4 26.7 20.3 105. 722. 82.6 438.
## 2 6 19.7 2.11 183. 1727. 122. 589.
## 3 8 15.1 6.55 353. 4593. 209. 2599.
和purrr
包中的map
族函数一样,across
也支持匿名函数。此外,across
函数也可以与summarise
之外的函数配合使用,这里使用mutate
函数:
purrr | 使用map族函数进行向量化运算
data %>%
mutate(across(c(mpg:hp), ~ .x^2)) %>%
head()
# Mazda RX4 441.00 36 25600 12100 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 441.00 36 25600 12100 3.90 2.875 17.02 0 1 4 4
## Datsun 710 519.84 16 11664 8649 3.85 2.320 18.61 1 1 4 1
## Hornet 4 Drive 457.96 36 66564 12100 3.08 3.215 19.44 1 0 3 1
## Hornet Sportabout 349.69 64 129600 30625 3.15 3.440 17.02 0 0 3 2
## Valiant 327.61 36 50625 11025 2.76 3.460 20.22 1 0 3 1
1.2 辅助函数
当待处理的变量的命名具有一定规律时,可以借助一些辅助函数来简化程序。
变量名具有相同前缀时,可以使用
starts_with
函数
如计算名称以d
开头的变量的平均值:
data %>%
group_by(cyl) %>%
summarise(across(starts_with("d"), mean))
## # A tibble: 3 x 3
## cyl disp drat
## * <dbl> <dbl> <dbl>
## 1 4 105. 4.07
## 2 6 183. 3.59
## 3 8 353. 3.23
变量名具有相同后缀时,可以使用
ends_with
函数
data %>%
group_by(cyl) %>%
summarise(across(ends_with("p"), mean))
## # A tibble: 3 x 3
## cyl disp hp
## * <dbl> <dbl> <dbl>
## 1 4 105. 82.6
## 2 6 183. 122.
## 3 8 353. 209.
变量满足一定条件,可以使用
where
函数
where
函数来自tidyselect
工具包。
data %>%
mutate(across(mpg:drat, as.factor)) %>%
group_by(cyl) %>%
summarise(across(where(is.numeric), mean))
## # A tibble: 3 x 7
## cyl wt qsec vs am gear carb
## * <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 4 2.29 19.1 0.909 0.727 4.09 1.55
## 2 6 3.12 18.0 0.571 0.429 3.86 3.43
## 3 8 4.00 16.8 0 0.143 3.29 3.5
mtcar
中的变量原本均为数值类型,这里先将mpg:drat
之间的变量转为因子类型后,再在across
函数中使用where
函数判断变量是否为数值类型,则已被转为因子类型的变量就不在此列了。
1.3 if_any
和if_all
函数
这两个函数主要与行筛选函数filter
配合使用。语法结构与across
函数类似,但.fns
参数对应的处理函数的返回值应为逻辑类型:
if_any:该行任意一个选中的列的元素在
.fns
函数中返回值为TRUE,则该行就会被filter
函数筛选出来;if_any:该行所有被选中的列的元素在
.fns
函数中返回值为TRUE,则该行才会被filter
函数筛选出来。
data %>%
filter(if_any(c(mpg, cyl), ~ (.x %% 3 == 0)))
## mpg cyl disp hp drat wt qsec vs am gear carb
## Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
## Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
## Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
## Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
## Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
## Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
## Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
data %>%
filter(if_all(c(mpg, cyl), ~ (.x %% 3 == 0)))
## mpg cyl disp hp drat wt qsec vs am gear carb
## Mazda RX4 21 6 160 110 3.9 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4
2 rowwise
rowwise
也来自dplyr
包,但它本身也是一个函数,功能类似于group_by
函数。
2.1 rowwise
函数
在不使用rowwise操作时,对多列变量使用mean
函数,其计算的是这些列所有元素的平均值,因此得到的结果对于每行是相同的:
data %>%
mutate(M = mean(c(mpg, cyl, disp, hp))) %>%
head()
## mpg cyl disp hp drat wt qsec vs am gear carb M
## Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 100.9219
## Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 100.9219
## Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 100.9219
## Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 100.9219
## Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 100.9219
## Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 100.9219
使用rowwise
函数后,其计算的是这些列每行的平均值:
data %>%
rowwise() %>%
mutate(M = mean(c(mpg, cyl, disp, hp))) %>%
head()
## # A tibble: 6 x 12
## # Rowwise:
## mpg cyl disp hp drat wt qsec vs am gear carb M
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 21 6 160 110 3.9 2.62 16.5 0 1 4 4 74.2
## 2 21 6 160 110 3.9 2.88 17.0 0 1 4 4 74.2
## 3 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1 57.0
## 4 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1 98.8
## 5 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2 140.
## 6 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1 88.5
与分类汇总函数连用:
data %>%
rowwise(mpg:hp) %>%
summarise(M = mean(c(mpg, cyl, disp, hp)))
## # A tibble: 32 x 5
## # Groups: mpg, cyl, disp, hp [31]
## mpg cyl disp hp M
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 21 6 160 110 74.2
## 2 21 6 160 110 74.2
## 3 22.8 4 108 93 57.0
## 4 21.4 6 258 110 98.8
## 5 18.7 8 360 175 140.
## 6 18.1 6 225 105 88.5
## 7 14.3 8 360 245 157.
## 8 24.4 4 147. 62 59.3
## 9 22.8 4 141. 95 65.6
## 10 19.2 6 168. 123 79.0
## # ... with 22 more rows
2.2 c_across
函数
c_across
的功能类似于across
函数,但它只有一个参数:
c_across(cols = everything())
data %>%
rowwise() %>%
mutate(M = mean(c_across(mpg:hp)))
## # A tibble: 32 x 12
## # Rowwise:
## mpg cyl disp hp drat wt qsec vs am gear carb M
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 21 6 160 110 3.9 2.62 16.5 0 1 4 4 74.2
## 2 21 6 160 110 3.9 2.88 17.0 0 1 4 4 74.2
## 3 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1 57.0
## 4 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1 98.8
## 5 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2 140.
## 6 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1 88.5
## 7 14.3 8 360 245 3.21 3.57 15.8 0 0 3 4 157.
## 8 24.4 4 147. 62 3.69 3.19 20 1 0 4 2 59.3
## 9 22.8 4 141. 95 3.92 3.15 22.9 1 0 4 2 65.6
## 10 19.2 6 168. 123 3.92 3.44 18.3 1 0 4 4 79.0
## # ... with 22 more rows
这里变量列序号是相连的,可以使用冒号
:
简化程序。
最后
以上就是正直铃铛为你收集整理的dplyr | 提高数据处理效率!数据框的colwise和rowwise操作的全部内容,希望文章能够帮你解决dplyr | 提高数据处理效率!数据框的colwise和rowwise操作所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复