前言
今天终于配置了图床,使用的是阿里云,虽然上传速度并不快,但比自己一张张的复制好太多了。之前用github配置,一直无法连接,果然还是花钱的更好!
在数据科学中的R语言[1]中学习了tidyverse一些常用的技巧之后,继续学习其进阶的内容,是进一步的扩展。本文是用Rmarkdown写的,一些语法参考了教程[2]
scoped函数
在tidyverse的学习中可以看到对mutate(),select()等函数的使用,事实上,只要在这些函数后面加上_all,_at,_if,就能形成新的变体函数,可以很方便地对数据的特定子集进行处理。
对数据框所有列的操作,可以用_all;
对数据框指定的几列操作,可以用_at;
对数据框符合条件的几列进行操作,可以用_if
Operate | _all | _at | _if |
---|---|---|---|
select() | select_all() | select_at() | select_if() |
mutate() | mutate_all() | mutate_at() | mutate_if() |
rename() | rename_all() | rename_at() | rename_if() |
arrange() | arrange_all() | arrange_at() | arrange_if() |
filter() | filter_all() | filter_at() | filter_if() |
distinct() | distinct_all() | distinct_at() | distinct_if() |
group_by() | group_by_all() | group_by_at() | group_by_if() |
summarise() | summarise_all() | summarise_at() | summarise_if() |
map() | map_all() | map_at() | map_if() |
modify() | modify_all() | modify_at() | modify_if() |
library(tidyverse)
data(iris)
iris %>% as_tibble()
image-20220908153728488
df_iris <- iris %>% head(5)
df_iris %>%
mutate_if(is.double,as.integer)#如果数据中有浮点型数据,就转换为整型
image-20220908153915118
df_iris %>% mutate_if(is.numeric,list(scale,log))#对数值型变量分别进行
#scale和log处理
image-20220908153947844
select_if()
df <- tibble::tibble(
x=c("a","b","c"),
y=c(1:3),
z=c(0,0,0)
)
df %>% select_if(is.numeric)#选择数值型的变量
image-20220908154041152
多条件情况下
df %>% select_if(
list(~(is.numeric(.)|is.character(.)))#多条件通常用列表来表示
)
image-20220908154110332
df %>% select_if(
list(~(is.numeric(.)&&mean(.)>1))#且的多条件语句
)
image-20220908154137336
summarise_if()
msleep <- ggplot2::msleep
msleep %>%
dplyr::group_by(vore) %>%
#dplyr::summarise_all(~mean(.,na.rm=TRUE)#里面存在非数值变量因此要使用条件判断
dplyr::summarise_if(is.numeric,mean,na.rm=TRUE)
image-20220908154201429
filter_if()
filter本身时筛选,有了if之后就变成条件筛选了。
msleep <- ggplot2::msleep
msleep %>%
dplyr::select(name,sleep_total) %>%
dplyr::filter(sleep_total>18)
image-20220908154228346
msleep %>%
dplyr::select(name,sleep_total) %>%
dplyr::filter(between(sleep_total,16,18))#筛选出sleep_total在16到18的数据
image-20220908154253609
msleep %>%
dplyr::select(name,sleep_total) %>%
dplyr::filter(near(sleep_total,mean(sleep_total),tol=0.5*sd(sleep_total)))
image-20220908154318722
msleep %>% select(name,sleep_total)
image-20220908154340962
filter_if()配合all_vars(),any_vars(),可以完成很多工作。比如,要求一行中所有变量值都大于150
mtcars <- mtcars %>% as_tibble()
mtcars
image-20220908154415560
mtcars %>% filter_all(all_vars(.>150))
image-20220908154444334
求一行中至少有一个变量的值大于150
mtcars %>% filter_all(any_vars(.>150))
image-20220908154505016
filter_at()针对某个特别的变量
mtcars %>% filter_at(vars(starts_with("d")),any_vars((.%%2)==0))#正对以d开头的变量,筛选出所有变量是偶数的行
image-20220908154532577
filter_if(.tbl,predicate,vars_predicate)用的比较多 参数解释: .tbl:数据框 .predicate:应用在列上的函数,一般作为列的选择条件 .vars_predicate:应用在一行上的函数,通过all_vars(),any_vars() 返回值决定是否选择该行。
mtcars %>% filter_if(~all(floor(.)==.),all_vars(.!=0))
#这里floor是向下取整,all_vars选取每一行不等于0的变量
image-20220908154614772
group_by()
mtcars %>% dplyr::group_by(cyl)#将数据按cyl进行分组
image-20220908154638409
mtcars %>% group_by_at(vars(cyl))
image-20220908154702993
iris %>% group_by_if(is.factor)#将数据按因子型变量进行分组
image-20220908154725816
group_split(),group_map,group_modify()
iris %>%
dplyr::group_by(Species) %>% #将数据按Species分组
dplyr::group_split()#然后将数据按照Species分割成多个列表
image-20220908154757509
也可以直接写成
iris %>%
dplyr::group_split(Species)
image-20220908154824031
利用purrr::map()函数对分组后的数据进行迭代,对数据分组建立回归模型,这是比较常用的。
iris %>%
dplyr::group_split(Species) %>%
purrr::map(~broom::tidy(lm(Petal.Length~Sepal.Length,data=.x)))#输出的模型结果是以列表的形式存在的,如果使用purrr::map_df
#输出的模型结果就是数据框的形式
image-20220908154907205
iris %>%
dplyr::group_by(Species) %>%
dplyr::group_map(~broom::tidy(lm(Petal.Length~Sepal.Length,data=.x)))
image-20220908154940549
对于group_map,就是输入数据框,然后分组,再对各分组进行处理形成多个数据框,最后将数据框以列表的形式输出。
group_modify()
group_modify才是输入数据框,输出数据框。
iris %>%
dplyr::group_by(Species) %>%
dplyr::group_modify(~broom::tidy(lm(Petal.Length~Sepal.Length,data=.x)))
image-20220908155007203
常用批量出图语句
nobel_winners=read.table("clipboard",header=TRUE)
nobel_winners %>%
dplyr::group_split(category) %>%
purrr::map(
~ggplot(data=.x,aes(x=prize_age))+
geom_density()+
theme_classic()+
theme(panel.grid=element_blank(),panel.background=element_rect(color="black",size=1))+
ggtitle(.x$category)
)
image-20220908155035451
nobel_winners=data.frame(nobel_winners)
nobel_winners %>%
dplyr::group_split(category) %>%
dplyr::group_map(~broom::tidy(
ggplot(data=.x,aes(x=prize_age)))+
geom_density()+
theme_classic()+
theme(panel.grid=element_blank(),panel.background= element_rect(color="black",size=1))+
#ggtitle(.y)
)
###对于这一段代码不知道为什么,一直报错,主要是group_mao()
报错如下:
Error in UseMethod("group_map") :
no applicable method for 'group_map' applied to an object of class "c('vctrs_list_of', 'vctrs_vctr', 'list')"
nobel_winners %>%
dplyr::group_by(category) %>%
dplyr::group_walk(
~ggsave(
paste0(.y,".png"),
ggplot(data=.x,aes(x=prize_age))+
geom_density()+
ggtitle(.y),
device="png",
path="C:\\Users\\wgw\\Desktop"
)
) %>%
invisible( )#这样可以将批量生成的图保存在指定的路径中
#很是方便
列名清理
数据框的列名,不要用有空格和中文,当数据中的列比较多,手动修改比较麻烦时,可以使用janitor::clean_names()
library(readxl)
library(janitor)
roster_raw <- read_excel("dirty_data.xlsx")
glimpse(roster_raw)
image-20220908155424637
可以看到有的列名并不规范,在后续的数据处理中很不方便 于是对列名进行处理:
roster <- roster_raw %>%
janitor::clean_names()
glimpse(roster)
image-20220908155501266
缺失值检查与处理
library(purrr)
airquality <- as_tibble(airquality)
airquality %>%
purrr::map(~sum(is.na(.)))#对airquality中的每个变量进行迭代
#计算存在缺失值的个数,以列表的形式输出
image-20220908155517833
airquality %>%
purrr::map_df(~sum(is.na(.)))
#map_df将输出结果以列表形式输出
image-20220908155539662
缺失值替换
airquality %>%
mutate_all(funs(replace(.,is.na(.),0)))
#将其中缺失值d替换成0
image-20220908155605421
airquality %>%
mutate_all(replace_na,replace=0)#缺失值替换为0,这样更简单
airquality %>%
mutate_if(is.numericreplace_na,replace=0)#将数值型的缺失值替换为0
airquality %>%
mutate_all(as.numeric) %>%
mutate_all(~coalesce(.,0))
#coalesce(a,b)其中a,b可以是两个长度一致的向量,数据框,a和b进行匹配,将对应位置缺失值替换为缺失值形成一个新的向量或数据框。具体例子如下:
tibble(
y=c(1,2,NA,NA,5),
z=c(NA,NA,3,4,5)
) %>%
mutate_all(~coalesce(.,0))
image-20220908155646265
参考资料
[1]数据科学中的R语言: https://bookdown.org/wangminjie/R4DS/tidyverse-dplyr-adv.html
[2]Rmarkdown 入门: https://cosx.org/2021/04/rmarkdown-introduction/