R语言学习:dplyr包数据操作
2022年第15周、16周。
这些周R语言学习,记录如下。
01
数据操作概述
数据操作是一个对数据加工处理以满足后续数据工作(分析或者建模)的过程。
数据操作主要做的事情,包括:
-
数据列的操作。
-
数据行的操作。
-
数据的聚合操作。
-
数据的其它操作。
我用dplyr包做数据操作,它功能强大,应用简便,编码易懂。
dplyr包做各种数据操作,无论多复杂,都可以分解5种基本的数据操作组合:
-
select()——选择列
-
filter()/slice()——选择行
-
arrange()——对行排序
-
mutate()——修改列/增加列
-
summarize()——数据聚合运算
它们都可以与
-
group_by()——分组
结合使用,以改变数据操作的作用域:
是作用于整个数据框,还是作用于数据框的每个分组。
上述函数组合使用,可以实现各种数据操作,不管是简单的,还是复杂的,都可以很好处理。
这些函数的相同之处:
-
第1个参数是数据框,便于管道操作,形如(df %>% select())
-
根据列名访问数据框的列,列名不用加引号
-
返回结果是一个新的数据框,不改变原数据框
从而,可以方便地实现:
把多个简单操作,依次用管道连接,实现复杂的数据操作。
02
列操作
数据的列操作,主要包括这些任务:
-
列选择
-
列删除
-
列顺序调整
-
列重命名
-
多列用函数处理
-
列增加
2.1 列选择
列选择,就是从数据集中选择所需列。
使用select()函数
1)用列名或者索引确定目标列
代码演示
mpg %>%
select(displ, drv, hwy) %>%
head(n = 10)
mpg %>%
select(3, 7, 9) %>%
head(n = 10)
2)用运算符确定目标列
-
用:选择连续的若干列
-
用!选择变量集合的余集
-
&和|选择变量的交集或者并集
-
c()合并多个选择
代码演示
mpg %>%
select(year:drv) %>%
head(n = 10)
mpg %>%
select(!year:drv) %>%
head(n = 10)
mpg %>%
select(c(year, drv, hwy)) %>%
head(n = 10)
3)用函数确定目标列
选择指定的列
-
everything()——选择所有列
-
last_col()——选择最后一列,可以带参数
选择列名匹配的列
-
starts_with()——以某前缀开头的列
-
ends_with()——以某后缀结尾的列
-
contains()——包含正则表达式的列
-
matches()——匹配正则表达式的列
-
num_ranges()——匹配数值范围的列
结合函数选择列
where()——应用一个函数到所有列,选择返回结果为TRUE的列
代码演示
mpg %>%
select(starts_with("m")) %>%
head(n = 10)
mpg %>%
select(ends_with("s")) %>%
head(n = 10)
mpg %>%
select(contains("c")) %>%
head(n = 10)
mpg %>%
select(contains("c") | ends_with("s")) %>%
head(n = 10)
mpg %>%
select(matches("m.*e")) %>%
head(n = 10)
mpg %>%
select(where(is.numeric)) %>%
head(n = 10)
mpg %>%
select(where(is.numeric)) %>%
select(where(~ sum(.x, na.rm = TRUE) > 1000)) %>%
head(n = 10)
2.2 列删除
列删除,就是从数据集中删除不需要的列。
用减号(-)删除列
代码演示
mpg %>%
select(-c(year, cyl, trans)) %>%
head(n = 10)
2.3 列顺序调整
可以根据被选择列的顺序调整列的顺序
代码演示
mpg %>%
select(ends_with("s"), year, hwy) %>%
head(n = 10)
mpg %>%
select(year, everything()) %>%
head(n = 10)
mpg %>%
relocate(where(is.numeric), .after = manufacturer) %>%
head(n = 10)
2.4 列重命名
使用set_names()函数为所有列重命名
使用rename()函数为部分列重命名,格式:新名 = 旧名
使用rename_with(.data, .fn, .cols)函数为选中cols采用函数fn对列重命名
代码演示
economics %>%
set_names(paste0("x", 1:6)) %>%
head(n = 10)
economics %>%
rename(日期 = date) %>%
head(n = 10)
economics %>%
rename_with( ~ paste0("new_", .x), matches("s")) %>%
head(n = 10)
2.5 多列用函数处理
使用强大的across()函数。
可以让0个或1个或多个函数作用所选择的列,即同时对所选择的多列应用若干函数。
across()函数的基本格式:
across()函数工作示意图:
across()函数的分解思维:
想要同时修改多列,只需要选出多列,把对一列做的事情写成函数即可,然后交给across()就行了。
代码演示
iris
# 获取iris数据集不同类别Sepal的长和宽的均值
iris %>%
select(starts_with("S")) %>%
group_by(Species) %>%
summarise(Sepal_Length_Mean = mean(Sepal.Length, na.rm = TRUE),
Sepal_Width_Mean = mean(Sepal.Width, na.rm = TRUE))
# 使用across函数
iris %>%
select(starts_with("S")) %>%
group_by(Species) %>%
summarise(across(c(Sepal.Length, Sepal.Width), mean, na.rm = TRUE))
2.6 列增加
用mutate()函数增加新列,返回原数据框并增加新列,默认加在最后一列。
参数.before,.after可以设置新列的位置。
代码演示
# 列增加
names(mpg)
mpg %>%
mutate(new_col = displ * 10) %>%
head(n = 10)
mpg %>%
mutate(new_col = displ * 10, .before = model) %>%
head(n = 10)
mpg %>% mutate(new_col = displ * 10, .after = manufacturer) %>%
head(n = 10)
03
行操作
行操作,就是获取数据子集。
行操作,包括这些任务。
-
行过滤
-
行切片
-
行删除
-
行排序
3.1 行过滤
用filter()函数,根据条件选择行
代码演示
mpg %>%
filter(model == 'a4') %>%
head(n = 5)
mpg %>%
filter(model == 'a4', year == 1999) %>%
head()
mpg %>%
filter(model == 'a4', (year == 1999 | drv == 'f')) %>%
head()
# 闭区间,between()函数
mpg %>%
filter(between(year, 1999, 2004)) %>%
head()
在限定列范围下做行选择
用if_all()或者if_any()函数与filter()函数结合。
代码演示
# 选择第8-9列,所有值都>20的行
mpg %>%
filter(if_all(8:9, ~ .x > 20)) %>%
head()
# 所有列范围,所有制都不是NA的行,类似na.omit()函数
mpg %>%
filter(if_all(everything(), ~ !is.na(.x))) %>%
head()
# 选定第8-9列,存在值大于>20的行
mpg %>%
filter(if_any(8:9, ~ .x > 20)) %>%
head()
3.2 行切片
用slice_*()函数。
参数n,指定要选择的行数
参数prop,按比例选择行
代码演示
# 行切片
mpg %>%
head(n = 10)
mpg %>%
slice(7:20) %>%
head()
mpg %>%
slice_head(n = 10)
mpg %>%
slice_head(prop = 0.1)
mpg %>%
slice_tail(n = 10)
mpg %>%
slice_tail(prop = 0.1)
mpg %>%
slice_sample(n = 10)
# 选择hwy前5大的行
mpg %>%
slice_max(hwy, n = 5)
# 选择hwy前5小的行
mpg %>%
slice_min(hwy, n = 5)
3.3 行删除
用distinct()函数删除重复行。
根据所有列或者指定列,判定重复,只保留第1个,其余行删除。
注意:默认只返回选择的列,若要返回所有列,设置参数.keep_all = TRUE
drop_na()函数,删除包含NA的行。
代码演示
# 行删除
# 删除重复行
mpg %>%
distinct()
mpg %>%
distinct(drv)
mpg %>%
distinct(drv, .keep_all = TRUE)
mpg %>%
drop_na()
3.4 行排序
用arrange()函数,对行排序,默认递增。
代码演示
# 行排序
# arrange()函数
mpg %>%
arrange(hwy) %>%
head()
mpg %>%
arrange(desc(hwy)) %>%
head()
mpg %>%
arrange(displ, desc(hwy)) %>%
head()
04
聚合操作
聚合操作是指对数据做汇总操作,可以对整个数据框或者对数据框的每个分组。
用group_by()函数创建分组。
访问或者查看分组情况。
代码演示
# 分组group_by()函数
iris_group <- iris %>%
group_by(Species)
iris_group
# 了解分组情况
# 分组键值
group_keys(iris_group)
# 查看每一行属于哪一分组
group_indices(iris_group)
# 查看每一组包含那些行
group_rows(iris_group)
# 解除分组
ungroup(iris_group)
其它分组函数
-
group_split():数据框分割多个分组,返回列表
-
group_nest():数据框分组,再做嵌套
-
purrr风格分组迭代,把函数.f依次应用到分组数据框.data的每个分组
代码演示
iris %>%
group_split(Species)
iris %>%
group_nest(Species)
# 提取每组的前两个观察
iris %>%
group_by(Species) %>%
group_map(~ head(.x, 2))
分组汇总
group_by() + summarise():对数据框分组,然后做汇总处理。
summarise() 与很多自带或自定的汇总函数连用。
代码演示
# 分组汇总
names(iris)
iris %>%
group_by(Species) %>%
summarise(n = n(),
Sepal_Length_Mean = mean(Sepal.Length, na.rm = TRUE),
Sepal_Length_Median = median(Sepal.Length, na.rm = TRUE))
summarise() 与 across() 结合,可以对多列进行操作。
代码演示
# 指定列
iris %>%
group_by(Species) %>%
summarise(across(starts_with("Sepal"), mean, na.rm = TRUE))
# 所有列
iris %>%
group_by(Species) %>%
summarise(across(everything(), mean, na.rm = TRUE))
mpg %>%
group_by(class) %>%
summarise(across(
where(is.numeric),
list(sum=sum, mean=mean),
na.rm = TRUE
))
增强可读性,把宽数据表示为长数据。
代码演示
mpg %>%
group_by(class) %>%
summarise(across(
where(is.numeric),
list(sum=sum, mean=mean),
na.rm = TRUE
)) %>%
pivot_longer(-class,
names_to = c("Vars", ".value"),
names_sep = "_")
代码演示
qs <- c(0.25, 0.5, 0.75)
mpg %>%
group_by(class) %>%
summarise(hwy_qs = quantile(hwy, qs, na.rm = TRUE),
q = qs)
# 长变宽
mpg %>%
group_by(class) %>%
summarise(hwy_qs = quantile(hwy, qs, na.rm = TRUE),
q = qs) %>%
pivot_wider(names_from = q, values_from = hwy_qs,
names_prefix = "q_")
# 分组统计
mpg %>%
count(class, sort = TRUE)
mpg %>%
group_by(hwy_level = cut(hwy,
breaks = c(10, 20, 30, 40, 50),
right = FALSE)) %>%
tally()
05
其他操作
排名和排序函数,常用min_rank()函数
代码演示
# 常用的min_rank()函数
mpg %>%
select(hwy, displ) %>%
slice_head(n = 10)
mpg %>%
select(hwy, displ) %>%
slice_head(n = 10) %>%
mutate(ranks = min_rank(desc(hwy)))
mpg %>%
select(hwy, displ) %>%
slice_head(n = 10) %>%
mutate(ranks = min_rank(desc(hwy))) %>%
arrange(ranks)
移位函数,lag(),向右移位,时间滞后;lead(),向左移位,时间超前。
代码演示
library(lubridate)
dt <- tibble(
day = as_date("2022-04-01") + c(0,4:6),
wday = weekdays(day),
sales = c(2,6,2,3),
balance = c(30, 25, -40, 30)
)
dt
# lag()时间滞后
dt %>%
mutate(sales_lag = lag(sales),
sales_delta = sales - lag(sales))
# lead()时间超前
dt %>%
mutate(sales_lead = lead(sales))
引用与反引用
enquo()让函数自动引用参数
!!反引用参数
as_label()修改结果列名
代码演示
grouped_mean <- function (data, summary_var, group_var) {
summary_var = enquo(summary_var)
group_var = enquo(group_var)
data %>%
group_by(!!group_var) %>%
summarise(mean = mean(!!summary_var))
}
grouped_mean(mtcars, mpg, cyl)
scatter_plot <- function (df, x_var,y_var) {
x_var = enquo(x_var)
y_var = enquo(y_var)
ggplot(data = df, aes(x = !!x_var, y = !!y_var)) +
geom_point() +
theme_bw() +
theme(plot.title = element_text(lineheight = 1, face = "bold", hjust = 0.5)) +
geom_smooth() +
ggtitle(str_c(as_label(y_var), " vs. ", as_label(x_var)))
}
scatter_plot(mtcars, disp, hp)
06
dplyr资料包
为了进一步学习,我准备了一份dplyr资料包。
这个资料包,包括:
-
1 dplyr包帮助文档,可以当作手册查看
-
2 dplyr包做数据变换的小手册,常用函数总结
-
3 dplyr和tidyr包做数据整洁小手册,常用函数总结
-
4 tidyverse套件做数据操作书籍,有章节总结dplyr包的使用
需要的你,直接给公众号回复信息20220428。
学习素材:
1https://willhipson.netlify.app/post/dplyr_across/dplyr_across/
2张敬信 (2022). R 语言编程:基于 tidyverse. 人民邮电出版社 , 北京
好了,我写完了。
我提供付费咨询和服务。
你我连接,相互交流,创造更多价值。
你或许还想看
喜欢本文点个在看
或关注下方公众号
你将感受到一个R语言学习人的灵魂
我的一个小号
数据科学与人工智能
公众号:R语言
作者:王路情
R语言学习者。
R语言深度使用者。
我用R语言做数据科学和医学科研。
只做付费咨询和服务。
就当你打赏我了。但价值远不止这几两碎银。
合作请加微信:luqin360
请关注“恒诺新知”微信公众号,感谢“R语言“,”数据那些事儿“,”老俊俊的生信笔记“,”冷🈚️思“,“珞珈R”,“生信星球”的支持!