R-tidyverse包-数据转换dplyr包进阶
R语言||干货!tidyverse包-数据转换dplyr包进阶
目录
[TOC]
简介
Dplyr(https://dplyr.tidyverse.org/)是一种数据操作语法,提供了一组一致的动词,帮助我们解决最常见的数据操作,比如行操作(filter、slice、arrange)、列操作(slelect、rename、mutate、relocate)、折叠操作(summarise)、合并table(left_join、right_join、inner_join)。查看包中的所有函数:
library(dplyr)
ls('package:dplyr')
- mutate:添加新列或者修改已存在列
- select:选择列变量
- filter:依据值过滤行
- summarise:将多个值降为单个summary
- arrange:行排序
- left_join:合并两个数据框
mutate函数介绍
常规用法
library(tidyverse) # or library(dplyr)
# 创建新列,一列或多列
starwars %>%
select(name, mass) %>%
mutate(
mass2 = mass * 2,
mass2_squared = mass2 * mass2, .before=name, # .before和.after设置新列插入的位置
test = 'test'
)
# 创建新列,按行进行统计
starwars %>% select(name, height, mass) %>%rowwise() %>% mutate(m = mean(c(height, mass)))
# 创建新列,根据数值排名创建列
starwars %>%
select(name, mass, homeworld) %>%
group_by(homeworld) %>%
mutate(rank = min_rank(desc(mass)))
# 删除列,设置NULL删除
starwars %>%
select(name, height, mass, homeworld) %>%
mutate(
mass = NULL
)
# 修改列,通过运算符修改
starwars %>%
select(name, height, mass, homeworld) %>%
mutate(
height = height * 0.0328084 # convert to feet
)
# 修改多列,利用across函数将多列字符串数据转换为因子
starwars %>%
select(name, homeworld, species) %>%
mutate(across(!name, as.factor))
# 保留或删除列,默认保留所有列
df <- tibble(x = 1, y = 2, a = "a", b = "b")
df %>% mutate(z = x + y, .keep = "all") # the default
df %>% mutate(z = x + y, .keep = "used")
df %>% mutate(z = x + y, .keep = "unused")
df %>% mutate(z = x + y, .keep = "none")
特殊用法
# 增加列列名为变量
col_name <- "new_column"
starwars %>% mutate(!!col_name := mass * height)
# 操作列名为变量
col_names <- c("height", "mass")
starwars %>% mutate(across(all_of(col_names), ~ .x * 2))
# 根据条件增加列
starwars %>% mutate(
gender = case_when(
sex == "male" ~ "Male",
sex == "female" ~ "Female",
TRUE ~ "Unknown"
)
)
# 根据条件增加列,针对所有以height开头的列,值乘10
starwars %>% mutate(across(starts_with("height"), ~.x*10), .keep='used')
# 根据条件修改列
starwars %>% mutate(
mass = if_else(mass > 100, "Yes", "No")
)
# 根据多列条件创建列
starwars %>% mutate(
special_condition = if_else(mass > 100 & height > 200, "Yes", "No")
, .keep='used')
select函数介绍
常规用法
library(tidyverse)
# For better printing
iris <- as_tibble(iris)
# 选择列,单列或者多列
starwars %>% select(homeworld, height, mass)
# 按索引选择列
starwars %>% select(1:3)
# 按范围选择列
starwars %>% select(name:mass)
# 反选,使用!或者-反选
starwars %>% select(!(name:mass))
iris %>% select(-c(Sepal.Length, Petal.Length))
# 按条件反选
iris %>% select(!ends_with("Width"))
# 按照多个条件选择,交集
iris %>% select(starts_with("Petal") & ends_with("Width"))
# 按照多个条件选择,并集
iris %>% select(starts_with("Petal") | ends_with("Width"))
# 按照多个条件选择,并集,其中一个条件反选
iris %>% select(starts_with("Petal") & !ends_with("Width"))
特殊用法
# 选择列为变量
col_names <- c("Sepal.Length", "Sepal.Width")
iris %>% select(all_of(col_names))
col_names <- c("Sepal.Length", "Sepal.Width", "test") # test不在iris数据中
iris %>% select(one_of(col_names))
filter函数介绍
常规用法
# 根据单个条件选择行
filter(starwars, species == "Human")
filter(starwars, mass > 1000)
# 根据多个条件选择行
filter(starwars, hair_color == "none" & eye_color == "black")
filter(starwars, hair_color == "none" | eye_color == "black")
filter(starwars, hair_color == "none", eye_color == "black")
# 取反
filter(starwars, !(hair_color == "none" & eye_color == "black"))
# 根据运算结果选择行
starwars %>% filter(mass > mean(mass, na.rm = TRUE))
starwars %>% group_by(gender) %>% filter(mass > mean(mass, na.rm = TRUE))
# 列名为变量
vars <- c("mass", "height")
cond <- c(80, 150)
starwars %>%
filter(
.data[[vars[[1]]]] > cond[[1]],
.data[[vars[[2]]]] > cond[[2]]
)
特殊用法
# 列名为变量
col_name <- "Species"
value_to_filter <- "setosa"
filtered_iris <- iris %>% filter(!!sym(col_name) == value_to_filter)
summarise函数介绍
常规用法
# 统计平均值和总行数
mtcars %>%
summarise(mean = mean(disp), n = n())
# 统计分组后平均值和总行数
mtcars %>%
group_by(cyl) %>%
summarise(mean = mean(disp), n = n())
# 列名是变量
var <- "mass"
summarise(starwars, avg = mean(.data[[var]], na.rm = TRUE))
summarise(starwars, avg = mean(!!sym(var), na.rm = TRUE))
特殊用法
# 分组,合并多行为一行
iris %>%
group_by(Species) %>% summarise(test=paste(Petal.Length, collapse=','))
# 多个函数
min_max <- list(
min = ~min(.x, na.rm = TRUE),
max = ~max(.x, na.rm = TRUE)
)
starwars %>% summarise(across(where(is.numeric), min_max))
starwars %>% summarise(
tibble(
across(where(is.numeric), ~min(.x, na.rm = TRUE), .names = "min_{.col}"),
across(where(is.numeric), ~max(.x, na.rm = TRUE), .names = "max_{.col}")
)
)
arrange函数介绍
常规用法
# 依据多行进行排序
arrange(mtcars, cyl, disp)
# 降序排序
arrange(mtcars, desc(disp))
# 先升序,再降序
arrange(mtcars, mpg, desc(hp))
# <p style="color: red;">分组排序,必须设置.by_group参数为TRUE</p>
mtcars %>% group_by(cyl) %>% arrange(desc(wt),.by_group = TRUE) %>% print(n=32)
# 列名是变量
var <- 'mpg'
arrange(mtcars, !!sym(var))
arrange(mtcars, .data[[var]])
# 选择多列进行排序
iris %>% arrange(pick(starts_with("Sepal")))
iris %>% arrange(across(starts_with("Sepal"), desc))
left_join函数介绍
install.packages('nycflights13')
library(nycflights13)
flights2 <- flights %>% select(year:day, hour, origin, dest, tailnum, carrier)
# 向左合并,指定按某列合并
flights2 %>% left_join(planes, by = "tailnum")
# 按照交集合并
df1 <- tibble(x = c(1, 2), y = 2:1)
df2 <- tibble(x = c(3, 1), a = 10, b = "a")
df1 %>% inner_join(df2)
# 向右合并
df1 %>% right_join(df2)
# 按照并集合并
df1 %>% full_join(df2)
其它常用函数介绍
rename重命名列
# 修改列名
iris <- as_tibble(iris)
rename(iris, petal_length = Petal.Length)
# 修改多列列名
lookup <- c(pl = "Petal.Length", sl = "Sepal.Length")
rename(iris, all_of(lookup))
# 修改多列列名,如果列名不存在,使用any_of
lookup <- c(lookup, new = "unknown")
try(rename(iris, all_of(lookup)))
rename(iris, any_of(lookup))
# 切换列名大小写,替换字符
rename_with(iris, toupper)
rename_with(iris, toupper, starts_with("Petal"))
rename_with(iris, ~ tolower(gsub(".", "_", .x, fixed = TRUE)))
# 使用paste修改列名时,设置recycle0 = TRUE防止空选
rename_with(
iris,
~ paste0("prefix_", .x, recycle0 = TRUE),
starts_with("nonexistent")
)
# rlang包中的set_names
set_names(head(mtcars), paste0(colnames(mtcars), "_foo"))
set_names(head(mtcars), paste0, "_foo")
relocate调整列顺序
df <- tibble(a = 1, b = 1, c = 1, d = "a", e = "a", f = "a")
# 默认最前
df %>% relocate(f)
# 指定顺序
df %>% relocate(a, .after = c)
df %>% relocate(f, .before = b)
df %>% relocate(a, .after = last_col())
# 指定顺序并改名
df %>% relocate(ff = f)
# 条件选择列
df %>% relocate(where(is.character))
df %>% relocate(any_of(c("a", "e", "i", "o", "u")))
slice选择行
# 选择第一行
mtcars %>% slice(1)
# 选择尾部一行或多行
mtcars %>% slice(n())
mtcars %>% slice(5:n())
# 去除指定行
slice(mtcars, -(1:4))
# 选择头部或尾部指定行
mtcars %>% slice_head(n = 5)
mtcars %>% slice_tail(n = 5)
# 排序后选择指定行
mtcars %>% slice_min(mpg, n = 5)
mtcars %>% slice_max(mpg, n = 5)
# slice_min()和slice_max()可能返回多行,因为排序后值相同,设置with_ties = FALSE,输出指定行
mtcars %>% slice_min(cyl, n = 1)
mtcars %>% slice_min(cyl, n = 1, with_ties = FALSE)
# 随机选择行
mtcars %>% slice_sample(n = 5)
mtcars %>% slice_sample(n = 5, replace = TRUE)
# 随机选择行,并设置权重
mtcars %>% slice_sample(weight_by = wt, n = 5)
across选择列
# 选择列,并用函数处理
iris %>% mutate(across(c(Sepal.Length, Sepal.Width), round))
iris %>%
group_by(Species) %>%
summarise(across(starts_with("Sepal"), ~ mean(.x, na.rm = TRUE)))
# 选择列,并用函数处理,并定义列名。.col表示原来的列名,.fn表示函数名
iris %>%
group_by(Species) %>%
summarise(across(starts_with("Sepal"), list(mean, sd), .names = "{.col}.fn{.fn}"))
# 选择列,只要某一行满足条件即保留行
iris %>%
filter(if_any(ends_with("Width"), ~ . > 4))
case_when条件语句
# 单列
x <- 1:70
case_when(
x %% 35 == 0 ~ "fizz buzz",
x %% 5 == 0 ~ "fizz",
x %% 7 == 0 ~ "buzz",
.default = as.character(x)
)
# 多列
starwars %>%
mutate(type = case_when(
height > 200 | mass > 200 ~ "large",
species == "Droid" ~ "robot",
.default = "other"
)) %>%
pull(type)
pull选择列
# 选择列,适用于一列,生成vector,和select函数最大的不同
mtcars %>% pull(cyl)
# 选择列,生成named vector
starwars %>% pull(height, name)