数据-R语言-图表-决策-Linux-Python

【tidyverse】part3:数据转化

2018-03-05  本文已影响225人  100gle

1. 数据操作:dplyr包应用

dplyr包是为数据分析提供了一系列快捷有效的操作,其中有五个关键函数基本可以解决掉大多数在数据转化预处理时的困难:

这五个核心函数构成了dplyr包的基础,虽然在plyr包中也会有相对应的函数,但是dplyr包是为data.frame数据集而设计的;

并且这五个关键函数都可以和group_by()来结合使用,因此总的来说是这六个函数为数据操作提供了十分重要的帮助;

同时,这几个函数的语法参数基本上都有共同之处:

  1. 第一个参数为数据集(data.frame)
  2. 之后便是一系列对数据集进行操作的命令
  3. 并且最后的结果并不会对原始数据产生任何影响,而是以一个新的数据集来展示

因此如果需要保存新的数据集,就需要额外赋值

本小节使用nycflights13::flights数据集

1.1 基本数据操作

筛选函数:filter

filter()函数之所以能对数据进行操作主要源于一系列的命令参数,这其中最重要的是通过比较运算符和逻辑运算符来对数据进行筛选:

逻辑运算符.png

)

除了能单独使用外,二者大多数都是搭配使用

#filter函数语法
filter(data, sequence_arguments,...)

#用法
flights %>% 
  filter(month == 11 | month == 12)

flights %>% 
  filter(arr_delay <= 120, dep_delay <= 120)

以上操作是针对非缺失值而言,filter的筛选命令生效是在条件(condition,有点类似于循环语句)为「TRUE」的情况下才能进行,往往并不包括「NA」值和「FALSE」条件
因此,如果筛选缺失值,不能直接使用比较运算符,只能通过R中的内置缺失值判断函数来进行「TRUE的操作」,比如:is.na(x)

df <- tibble(x = c(1, NA, 3))
filter(df, is.na(x) | x > 1)

查看更多参数可以使用?filter()查阅帮助文档

排列函数:arrange

排列函数与筛选函数也有着筛选的功能,但更多的是起到排序的作用

#arrange函数语法
arrange(data, sequence_argument,...)

#用法
arrange(flights, year, month, day)

如果想对数据集进行降序排列,则可以使用desc(var)参数

arrange(flights, desc(arr_delay))

如果数据集中存在缺失值,缺失值无论是升序还是降序,永远都排列在最后面

选取函数:select

在一个数据集中有成千上百个变量是不常见的,当然在分析过程中除了要对数据进行预处理外,更重要的是缩小要关注的变量的范围,而select()函数就可以为这一过程提供十分快捷、有效的操作

#select函数语法
select(data, sequence_argument, everything())

同时还有一个与select()函数有着相似功能的函数,但是其并不履行着选取的功能,反而是起着重命名的作用——rename()函数:

#rename函数语法
rename(data, new_var_name = old_var_name,...)

当然select()函数也可以起到这功能,但是二者有着差别:

添加变量函数:mutate

mutate()函数是一个能在数据集中根据已有的变量,来添加新变量的函数;在R的基础函数中transform()函数也起着相同的作用

#mutate函数语法
mutate(data, new_var = old_var_argument,...)

#运用例子
flights_sml <- flights %>% 
  select(year:day, ends_with('delay'),
         distance, air_time) %>% 
  mutate(
    gain = arr_delay - dep_delay,
    speed  = distance / air_time *60
 )

#使用预新建变量再生成其他新变量
flights_sml <- flights %>% 
  mutate(
    gain = arr_delay - dep_delay,
    hours = air_time /60,
    gain_per_hour = gain / hours
 )

如果仅想保留新建的变量,则将mutate()函数替换为transmute()函数即可;
虽然添加变量函数便于理解,但是可能会涉及到其他运算来进行更复杂的变量生成:

分组与输出统计量函数:group_by和summarize

summarize()函数如果是单独使用时效果并不是特别好,但是如果搭配group_by()函数,进行分组统计输出,就能起到意想不到的效果(如分组求和等);这就有些类似于R基础函数aggregate()

#分组与输出统计量函数语法
group_by(data, by_vars, ...)
summarize(data, new_col = func(var, na.rm =))

#运用案例1
by_day <- group_by(flights, year,month, day) %>% 
  summarize(delay = mean(dep_delay, na.rm = T))
by_day

#运用案例2
delays <- flights %>% 
  group_by(dest) %>% 
  summarize(
    count = n(),
    dist = mean(distance, na.rm = T),
    delay = mean(arr_delay, na.rm = T)
  ) %>% 
  filter(count > 20, dest != 'HNL')

小结

1.2 联结

有时一个数据分析很难只会涉及到一个数据集,还有可能涉及到其他的数据集,因此需要额外的将一个数据集和另一个相关的数据集进行「联结」,从而结合创造出一个新的、包含自己需要的变量的数据集

flights数据集.png

因此这就需要使用到有关「联结」,而dplyr包就提供了类似于SQL数据库的「JOIN语句」:

而联结在SQL中又是通过「键-值」来实现联结的

「键」又有两种:

一个变量(列)既可以是主键,也可以是外键,因此正确识别并找出一个数据集的「键」,才能为联结地开展提供便利;通过「键」能将不同数据集的多个观察值通过键联结起来(回想分散与聚合函数使用到的key和value)

添加联结

添加联结主要有以下两种类型:

通过图片来理解外联结或许会更直白一点 外联结图示.png

Venn图

联结逻辑Venn图.png
#join函数语法
*_join(x, y, by = 'var')

R基础的函数中有提供merge()函数,用法与join类似

以上情况都是基于「键」为唯一时才能起到真正的作用,如果键不唯一时,可能会出现一键对多值的情况发生

筛选联结
添加联结是在保留原有的数据集的情况下,再加入其他数据集的变量,通过一个共有变量来联结两个数据集;而筛选联结则进一步加深了保留的操作,有保留和删除两种

集合操作符

小结

2. 字符串处理:stringr包应用

2.1 字符串基础

字符串创建

字符串函数

字符串筛选

使用str_sub()函数可以筛选出向量中的特定字符串

#str_sub函数语法
str_sub(string, start = 1L, end = -1L)

#运用案例
x <- c("Apple", "Banana", "Pear") 
str_sub(x, 1, 3) #如果是负数,则是倒数

字符样式转换

对于字符大小写转换,stringr包提供了三个基本的函数:

这三个函数中都有一个locale参数,可以用来指定文本的语言类型,默认为英语

2.2 正则表达式

stringr包提供了两个匹配的函数:

两者语法一致

str_view(string, pattern, match = NA)
str_view_all(string, pattern, match = NA)

在匹配过程中,往往可能需要用到其他符号:

str_view(c('abc','a.c','bdf'), 'a\.c') #报错
str_view(c('abc','a.c','bdf'), 'a\\.c') #正确显示

2.3 字符匹配

2.3.1 锚键匹配

锚键时用来匹配开头和结尾为某个字符的正则表达式:

x <- c("apple", "banana", "pear") 
str_view(x, "^a")
str_view(x, 'a$')

2.3.2 字符类型与其他选项匹配

对于包含数字的文本以及包含分隔线的字符,以下有4个方式可以进行匹配:

在实际匹配中,可以使用逻辑运算符来表示其他选项,这样就会匹配每一种可能的情况:

str_view(c('grey','gray'), 'gr(e|a)y')

2.3.3 重复匹配

有时在一个字符串种会出现重复出现的字符,因此有三种方式可以来进行重复出现情况的匹配:

x <- "1888 is the longest year in Roman numerals: MDCCCLXXXVIII"
str_view(x, "CC?")
str_view(x, "CC+")
str_view(x, "CC*")

初次之外,还可以使用花括号的形式来表达次数:

简单可以理解为花括号为一种区间的表达形式,且这种区间时闭区间

str_view(x, "C{2}")
str_view(x, "C{2,}")
str_view(x, "C{,3}")
str_view(x, "C{2,3}")

并且默认的匹配往往都是将所有字符都匹配出来,但是如果仅仅是想快捷的找出存在的字符串,而不需要匹配那么多字符,可以在花括号后面加上一个「?」

2.4 stringr工具

stringr包除了提供基础的正则表达式检索之外,还提供了其他额外的实用功能:

明确匹配字符串

stringr包提供了返回逻辑值的字符串匹配函数str_detect(),用来快速检索匹配字符串中是否包含字符并返回逻辑值结果,有点类似于R基础的is.*()函数族用法

#str_detect函数语法
str_detect(string, pattern)

#运用案例
x <- c("apple", "banana", "pear") 
str_detect(x, "e")

str_count()str_detect()的进阶版本:除了返回逻辑值外,还能计算包含字符的字符串频数

提取匹配内容

str_extract()函数提供提取匹配内容的功能,通过匹配相应的字符,返回符合匹配条件的观测值集合

color_match <- str_c(colors, collapse = "|")
has_color <- str_subset(sentences, color_match)
matches <- str_extract(has_color, color_match)
head(matches)

这仅仅是进行单项匹配,如果还希望进行全匹配,可以使用str_extract_all()

替代匹配

stringr包提供了两个参数来批量替代掉文本中的字符:

二者语法一致

#函数语法
str_replace(string, pattern, replacement)

分割字符串

类似于R基础函数中的split()函数,stringr包也提供了一个用来分割字符串的函数str_split()

#str_split函数语法
str_split(string, pattern, n = Inf, simplify = FALSE)

除了使用分隔符来分割字符外,还可以使用字符、线、句子、单词等用来分割字符,但这就需要用到boundary()函数来指定

x <- "This is a sentence. This is another sentence." str_view_all(x, boundary("word"))
str_split(x, boundary("word"))[[1]]

小结

3. 因子处理:forcats包应用

forcats包是专门用来处理分类变量的包,但是没有包含在tidyverse的核心包中,因此需要自己额外安装并加载

if(!require(forcats))(install.packages('forcats'))
library(forcats)

一般而言,如果不指定levels,那么因子变量的值(英文)排序会根据开头的字母表来排序

R基础函数中提供了查看一个因子类型变量的水平以及标签的函数:

处理因子变量面临的最主要的两个问题是:

调整因子顺序

改变因子水平的第一步是对因子进行可视化,这样可以更为直观的发现因子水平的分布,之后可以使用fct_reorder()函数对因子重新进行水平的调整

relig <- gss_cat
fct_reorder(relig$relig, relig$tvhours)

该函数在进行可视化展示时可以省去排序调整这一步骤,能方便快捷进行分析

同时forcats包提供了能将特定水平值提前到最前面的函数:
fct_relevel()

对于需要统计各因子频数的情况,可以搭配fct_infreq()fct_rev()两个函数来使用:

gss_cat %>% 
  mutate(relig = relig %>% 
           fct_infreq() %>% 
           fct_rev()) %>% 
  ggplot(aes(relig)) + 
  geom_bar() +
  coord_flip() #由于各值标签过长,因此转为横向条形图

调整因子水平

forcats包提供了用于调整因子水平的函数:fct_recode(),可以方便快捷的调整因子水平,同时可以将一个新的水平标签直接赋值给旧的水平标签

gss_cat %>% mutate(partyid = fct_recode(partyid, 
    "Republican, strong" = "Strong republican", 
    "Republican, weak" = "Not str republican", 
    "Independent, near rep" = "Ind,near rep", 
    "Independent, near dem" = "Ind,near dem", 
    "Democrat, weak" = "Not str democrat", 
    "Democrat, strong" = "Strong democrat", 
    "Other" = "No answer", 
    "Other" = "Don't know", 
    "Other" = "Other party" 
    )) %>% 
    count(partyid)

如果并不想指定新的因子水平,而是想直接将几个因子水平合并为新的水平,则可以使用fct_collapse()函数:

gss_cat %>% 
  mutate(
    partyid = fct_collapse(partyid,
    other = c("No answer", "Don't know", "Other party"),
    rep = c("Strong republican", "Not str republican"),
    ind = c("Ind,near rep", "Independent", "Ind,near dem"),
    dem = c("Not str democrat", "Strong democrat")
    )) %>% 
  count(partyid)

同时fct_lump()函数也提供类似于折叠合并的功能,但是并没有修改水平标签名的功能,并且还需要自己通过参数n=#来手动设置分组的数目

gss_cat %>% 
    mutate(relig = fct_lump(relig, n = 10)) %>% 
    count(relig, sort = TRUE) %>% 
    print(n = Inf)

小结

4. 时间序列处理:lubridate包应用(暂放)

小结

上一篇 下一篇

猜你喜欢

热点阅读