【tidyverse】part2:数据整理

1. tibble数据

1.1 tibble数据简介

“Tibbles are data frames, but they tweak some older behaviors to make life a little easier.”
——Hadley Wickham《R for data science》

Tibble是数据框的一种形式,但是比数据框更整洁,结构更加紧凑,可以理解为tidy table之意

  • 如果加载了tidyverse,统一采用tibble格式的数据集

1.2 tibble数据创建

可以通过tibble()函数来像data.frame()一样来创建tibble数据

tibble(
    x = 1:5, 
    y = 1, 
    z = x ^ 2 + y
)

或者可以通过转置函数as_tibble()来将data.frame格式的数据转化为tibble格式的数据

as_tibble(mtcars)

  • 需要注意的是,不同于传统的R语言as.*一类函数的用法,对于变量类型的转换,使用的是parse_*函数族,而对于数据集则使用的是as_*函数族
  • 并且转化时,tibble数据不会改变原始数据的任何信息

如果是想以表格的形式输入数据,可以使用tribble()函数来创建,只是与tibble()格式有点小小的不同:

tribble(
  ~x, ~y, ~z,
  #--/--/----
  'a', 2, 3.6,
  'b', 3, 2.5
)
  • 这种格式变量通常以「~」开头
  • 使用注释符号来分隔符会使得输入能整洁且便于对应表头
  • 注意不要漏掉「,」半角逗号

1.3 tibble数据与传统data.frame

tibble数据与data.frame数据相比主要在以下两个方面有所不同:

  • 打印输出
  • 子集索引

打印输出

tibble数据输出到console上只会显示前10行,和所有列;这对于大数据量而言是十分有益的

  • 如果想获取更详细的信息,使用str()函数来提取

如果想明确输出具体的打印信息,可以在print()函数中设置n=#width=Inf,分别对应行和列的数量;
当然还可以设定默认打印输出的参数,主要有以下三个选项可供修改:

# 最大最小打印值
options(tibble.print_max = m, 
        tibble.print_min = n)
        
# 输出所有行
options(dplyr.print_min = Inf)

# 输出所有列
options(tibble.width = Inf)
  • 如果想获取更多可以使用package?tibble查看

子集索引

tibble索引与传统data.frame格式索引一致,主要差别在:
tibble数据使用的是严谨的全部匹配,如果试图索引一个不存在的列,其会生成警告

小结

  • tibble是data.frame的一种,但结构更紧凑、简洁
  • 创建tibble数据有tibble()tribble()两个函数,也可以通过as_tibble()来转换
  • tibble与data.frame的区别在于输出打印和子集索引上,并且R许多基础的函数功能可能对与tibble数据并不起作用,因此如果需要用到某些函数功能时,可能需要将tibble数据转换成data.frame格式

2. 数据整理之tidyr包应用

2.1 什么是tidy数据

tidy数据表示的是已经整理好的、整洁的数据,通常现实中的数据许多都是混乱,甚至是「脏」的,将这些数据进行处理后所得到的数据就可以称之为tidy数据

tidyverse包中的其他包都是为tidy数据而设计的;也可以说,tibble格式的数据就是tidy数据的表现形式;通识tidy数据有以下三个方面的特征:

  • 每个变量都对应着单独的一列
  • 每条记录都对应着单独的一行
  • 每个观察值都对应着单独的单元格

2.2 数据预处理函数

2.2.1 分散与聚合

在现实的分析中,往往需要对数据进行的初步处理,使数据变得整洁:

  1. 第一步是需要确定变量和观察值是哪些
  2. 使确定好的变量和观察值能够分别很好地对应列和行

spread函数

分散函数是将变量中的值拆分成新的变量,这个过程概括为就是将为成「列」的值,进行拆分,并指定其他列作为「值」,组合成「键-值」对的形式

#spread函数语法
spread(data, key= , value=, )

#以table2数据集为例子
table2 #查看数据集
table2 %>% 
  spread(key = 'type', value = 'count')

type列的值拆分作为「键」,count列的值则作为每个键下的「值」,进而将变量值进行拆分

gather函数

在一些数据中存在的问题是,列名并非是变量名,反而是变量的某个具体值,因此就需要将这些已经成为列的「值」聚合到一起,还原成其本来归属的变量里;聚合函数与分散函数是一对互逆的过程

#gather函数语法
gather(data, set_colums, key= , value=, ...)

# 以tidyverse包中的table4a数据为例
table4a #查看数据集
table4a %>% 
  gather(`1999`, `2000`, 
  key = 'year', value = 'cases')

简而言之,gather函数就是将成为列的「值」进行「键-值」形式的拆分:

  • 每个19992000都对应着一个不同的值;
  • 因此根据gather函数中的keyvalue参数不难发现,前者是为19992000指定新的「键」,即变量;而后者则为这些「值」指定新的变量

通过观察可以很容易看出:

  • gather()函数是将数据宽格式数据转化为长且窄的格式数据,这对于ggplot2包的使用极其有用
  • spread()函数则是将长格式数据转化为短且宽格式数据

2.2.2 拆分与黏合

分散与聚合是处理将变量与值进行转化时使用到的函数;而有时需要将一个列中的值拆分成两个变量的值,或者将两个变量的值组合成一个新的变量的值,这时候就需要使用到拆分与黏合函数

separate函数

#separate函数语法
separate(data, col, into= )

#以table3数据集为例子
table3 #查看数据集
table3 %>%
    separate(rate, into=c('cases','population'))
  • 从语法和例子上可以清楚的了解到separate参数的指定过程
  • 但是该函数默认是将非字母和数字的字符进行分隔,如果希望指定分隔符,则需要额外使用sep= ''参数
    • 如果是要将数字进行分隔,那么使用sep参数时需要注意位数的正负:

      • sep=1时,则是从左往右进行位数拆分
      • sep=-1时,则是从右往左进行位数拆分
  • 并且要注意拆分后变量的类型,有可能会并非正确的数据类型,因此需要在转换时加上convert =T参数来确保变量转换成正确的类型

unite函数

同分散与聚合一样,拆分与黏合函数同样时一对互逆的函数与过程;黏合函数是将两列变量的值黏合到一起,组成新的变量

#unite函数语法
unite(data, new_col, old_cols)

#接着separate的例子
table3 %>%
    separate(year, into=c('century','year')) %>%
    unite(new_year, century, year)
  • unite()函数默认使用「_」来联结黏合的值,可以通过sep参数来调整
  • 拆分与黏合的语法基本一致,不同的是在第二个参数的使用上

2.2.3 缺失值处理

缺失值的存在方式主要可能有两种:

  1. 直接用NA来表明
  2. 间接的使用其他方式来呈现:如应该出现的却没有出现、NULL、stata中的「.」等,这些都有可能是缺失值

complete

complete()函数是将数据集中所有不重复的列组合到一起进行展示,对于原始数据缺失的值用NA来进行填充

#complete函数语法
complete(data, unique_cols,...)

fill

fill()函数通过名称可以很容易得知,这是将缺失值进行替换的函数:

#设定数据集
treatment <- tribble( 
        ~ person,            ~ treatment, ~response, 
        #-----------------/------------/----------/
        "Derrick Whitmore",             1,         7, 
        NA,                             2,        10, 
        NA,                             3,         9, 
        "Katherine Burke",              1,         4
)

treatment %>% 
  fill(person)

fill()函数默认是用NA值的前面一个值来覆盖NA,如果想调整方向,可以使用.direction=c('up')参数来进行调整

  • 如果忘记参数可以使用?fill查看帮助文档

小结

  • 本小节主要设计三组对于数据预处理的函数:分散与聚合、拆分与黏合、缺失值展示与填充
  • 分散与聚合是将以「键-值」对的形式来展开转化
  • 拆分与黏合是将单个值或多个变量拆分或黏合成一个或多个变量的过程
  • 缺失值的存在方式有直接和间接两种

运用案例

使用「who」数据集,对数据集进行整理并最后得到tidy数据

library(tidyverse)
who

查看数据集,可以发现:

  • iso2和iso3表示地名
  • year为变量,不需要变动
  • 其他一系列的函数同名较多,可能为值,需要进行聚合
who %>%
    gather(new_sp_m014:newrel_f65, 
    key = "key", value = "cases", na.rm = TRUE)

对数据列进行聚合,并且删除缺失值

之后通过查看key变量的频数可以发现每个取值都是有规律的,都是由「_」下划线来分隔,因此只需要以「_」来分隔来决定是否对分隔后的变量保留即可;
但是有一点需要注意的是,newrel的一系列值并没有下划线,因此需要额外使用到stringr包中的str_replace来对这一系列值进行分隔符添加,然后再进行分隔

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

#添加下划线
who %>%
    mutate(key = stringr::str_replace(key, 'newrel', 'new_rel') %>%
    separate(key, c('new', 'type', 'sexage'), sep = '_')

最后需要再对sexage进行拆分,然后删除冗余的变量,保留需要的变量即可


who %>%
    select(-iso2, -iso3, -new) %>%
    separate(sexage, c('sex', 'age'), sep = 1))
  • 注意sep=1是指定从左往右分隔1位数

完整代码:

who %>% 
  gather(new_sp_m014:newrel_f65, 
         key = 'key', value = 'cases', na.rm = T) %>% 
  mutate(key = stringr::str_replace(key, 'newrel', 'new_rel')) %>% 
  separate(key, c('new', 'type', 'sexage'), sep = '_') %>% 
  select(-iso2, -iso3, -new) %>% 
  separate(sexage, c('sex', 'age'), sep = 1)

  • 使用到的stringr包的str_replace()函数以及select()mutate()函数为后面章节的函数
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容