逐禅

V1

2022/09/08阅读:18主题:兰青

tidyverse进阶

tidyverse进阶


前言

今天终于配置了图床,使用的是阿里云,虽然上传速度并不快,但比自己一张张的复制好太多了。之前用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
image-20220908153728488
df_iris <- iris %>% head(5)
df_iris %>% 
  mutate_if(is.double,as.integer)#如果数据中有浮点型数据,就转换为整型
image-20220908153915118
image-20220908153915118
df_iris %>% mutate_if(is.numeric,list(scale,log))#对数值型变量分别进行
#scale和log处理
image-20220908153947844
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
image-20220908154041152

多条件情况下

df %>% select_if(
  list(~(is.numeric(.)|is.character(.)))#多条件通常用列表来表示
)
image-20220908154110332
image-20220908154110332
df %>% select_if(
  list(~(is.numeric(.)&&mean(.)>1))#且的多条件语句
)
image-20220908154137336
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
image-20220908154201429

filter_if()

filter本身时筛选,有了if之后就变成条件筛选了。

msleep <- ggplot2::msleep
msleep %>% 
  dplyr::select(name,sleep_total) %>% 
  dplyr::filter(sleep_total>18)
image-20220908154228346
image-20220908154228346
msleep %>% 
  dplyr::select(name,sleep_total) %>% 
  dplyr::filter(between(sleep_total,16,18))#筛选出sleep_total在16到18的数据
image-20220908154253609
image-20220908154253609
msleep %>% 
  dplyr::select(name,sleep_total) %>% 
  dplyr::filter(near(sleep_total,mean(sleep_total),tol=0.5*sd(sleep_total)))
image-20220908154318722
image-20220908154318722
msleep %>% select(name,sleep_total)
image-20220908154340962
image-20220908154340962

filter_if()配合all_vars(),any_vars(),可以完成很多工作。比如,要求一行中所有变量值都大于150

mtcars <- mtcars %>% as_tibble()
mtcars
image-20220908154415560
image-20220908154415560
mtcars %>% filter_all(all_vars(.>150))
image-20220908154444334
image-20220908154444334

求一行中至少有一个变量的值大于150

mtcars %>% filter_all(any_vars(.>150))
image-20220908154505016
image-20220908154505016

filter_at()针对某个特别的变量

mtcars %>% filter_at(vars(starts_with("d")),any_vars((.%%2)==0))#正对以d开头的变量,筛选出所有变量是偶数的行
image-20220908154532577
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
image-20220908154614772

group_by()

mtcars %>% dplyr::group_by(cyl)#将数据按cyl进行分组
image-20220908154638409
image-20220908154638409
mtcars %>% group_by_at(vars(cyl))
image-20220908154702993
image-20220908154702993
iris %>% group_by_if(is.factor)#将数据按因子型变量进行分组
image-20220908154725816
image-20220908154725816

group_split(),group_map,group_modify()

iris %>% 
  dplyr::group_by(Species) %>% #将数据按Species分组
  dplyr::group_split()#然后将数据按照Species分割成多个列表
image-20220908154757509
image-20220908154757509

也可以直接写成

iris %>% 
  dplyr::group_split(Species)
image-20220908154824031
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
image-20220908154907205
iris %>% 
  dplyr::group_by(Species) %>% 
  dplyr::group_map(~broom::tidy(lm(Petal.Length~Sepal.Length,data=.x)))
image-20220908154940549
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
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
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
image-20220908155424637

可以看到有的列名并不规范,在后续的数据处理中很不方便 于是对列名进行处理:

roster <- roster_raw %>% 
  janitor::clean_names()

glimpse(roster)
image-20220908155501266
image-20220908155501266

缺失值检查与处理

library(purrr)
airquality <- as_tibble(airquality)
airquality %>% 
  purrr::map(~sum(is.na(.)))#对airquality中的每个变量进行迭代
#计算存在缺失值的个数,以列表的形式输出
image-20220908155517833
image-20220908155517833
airquality %>% 
  purrr::map_df(~sum(is.na(.)))
#map_df将输出结果以列表形式输出

image-20220908155539662
image-20220908155539662

缺失值替换

airquality %>% 
  mutate_all(funs(replace(.,is.na(.),0)))
#将其中缺失值d替换成0
image-20220908155605421
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
image-20220908155646265

参考资料

[1]

数据科学中的R语言: https://bookdown.org/wangminjie/R4DS/tidyverse-dplyr-adv.html

[2]

Rmarkdown 入门: https://cosx.org/2021/04/rmarkdown-introduction/

分类:

人工智能

标签:

数据挖掘

作者介绍

逐禅
V1