[R数据科学]tidyverse数据清洗案例详解
介绍
本中你将学习在R中数据处理简洁的方法,称为
tidy data
。将数据转换为这种格式需要一些前期工作,但这些工作从长远来看是值得的。一旦你有了整洁的数据和一些包提供的整洁工具,您将花费很少时间将数据从一种表示转换到另一种,从而可以将更多的时间花在分析问题上。本文将为您提供整理数据的实用介绍以及tidyr包中附带的工具。如果你想了解更多的基本理论,你可能会喜欢发表在《统计软件杂志》上的tidy data论文[1]。
本文框架
数据清洗案例
我们主要通过一个案例,来了解如何整洁数据,并将案例中的各个有用函数进行详细解读。该例子来自《R for data science》[2],案例数据来自
tidyr::who
,其包含按年份,国家,年龄,性别和诊断方法细分的结核病(TB)病例。数据来自2014年世界卫生组织《全球结核病报告》[3]。library(tidyverse) #加载包
who #数据展示
这是一个非常典型的现实示例数据集。它包含冗余列,奇数变量代码和许多缺失值。我们需要采取多个步骤来对其进行整理。
不是变量的列汇集在一起
首先将不是变量的列聚集在一起。所包含的列包括:
country
,iso2
和iso3
是三个指定国家/地区的变量。year
是一个变量。- 变量名中给出的结构(例如
new_sp_m014
,new_ep_m014
,new_ep_f014
)可能是值,而不是变量。
因此,我们需要将从
new_sp_m014
到newrel_f65
的所有列汇总在一起。我们用通用名称"key"
来表示他们。我们知道单元格代表案件数,因此我们将变量数存储在cases
中,并用na.rm
去除含有缺失值的行。这里使用pivot_longer()
将数据变长,具体见后面函数详情。who1 <- who %>%
pivot_longer(
cols = new_sp_m014:newrel_f65,
names_to = 'key',
values_to = 'cases',
values_drop_na = T
)
who1
对
key
进行计数,我们可以得到一些有关值结构的提示:who1 %>% count(key)
其中
key
的具体含义,查阅可得:- 每列的前三个字母:新、旧病例。
- 之后两个字母:结核的类型。
rel
代表复发病例ep
代表肺外结核病例sn
代表无法通过肺部涂片诊断(涂片阴性)的肺结核病例sp
代表可被诊断为肺部涂片(涂片阳性)的肺结核病例
- 第六字母:结核病患者的性别。男性(
m
)和女性(f
) - 其余数字给出了年龄段。数据集将案例分为七个年龄组:
- 014 = 0 – 14岁
- 1524 = 15 – 24岁
- 2534 = 25 – 34岁
- 3544 = 35 – 44岁
- 4554 = 45 – 54岁
- 5564 = 55 – 64岁
- 65 = 65岁或以上
替换数据
我们需要对列名称的格式进行较小的修正:将
new_rel
替换为newrel
(很难在这里找到它,但是如果您不修正它,我们将在后续步骤中出错)。这里使用了stringr
包中的str_replace()
,将newrel
替换new_rel
。who2 <- who1 %>%
mutate( names_from = stringr::str_replace(key,'newrel','new_rel')
)
who2
字符分割
接下来就是将
key
中的字符进行分割,我们使用separate()
对字符进行两次分割。1.将在每个下划线处拆分代码。
who3 <- who2 %>%
separate(key,c('new','type','sexage'),sep = '_')
who3
利用
select()
删除没用的列:new,iso2,iso3
。who3 %>% count(new)
who4 <- who3 %>% select(-new,-iso2,-iso3)
who4
将分离 sexage
到sex
和age
通过的第一个字符后拆分:
who5 <- who4 %>%
separate(sexage,c('sex','age'),sep=1)
who5
这时,who数据集整洁!
可视化
数据清洗完毕,就可以做一些初步的可视化,探索性分析.这里简单绘制了
前几个国家不同年份,不同性别的结核病病例总数。
who5 %>% group_by(country,year,sex) %>% filter(year<2003) %>%
count() %>%
head(100) %>%
ggplot(aes(x=as.factor(year),y=n,fill=country))+geom_col() +facet_wrap(~sex,nrow = 1)+
scale_fill_brewer(palette = "Paired")
复杂的管道函数
事实上你可以直接只用管道函数构建一个复杂的函数,这样做去除了中间变量,而且可读性很强,强烈推荐。
who %>%
pivot_longer(
cols = new_sp_m014:newrel_f65,
names_to = "key",
values_to = "cases",
values_drop_na = TRUE
) %>%
mutate(
key = stringr::str_replace(key, "newrel", "new_rel")
) %>%
separate(key, c("new", "var", "sexage")) %>%
select(-new, -iso2, -iso3) %>%
separate(sexage, c("sex", "age"), sep = 1)
所用函数详细解释
pivot_longer()、poivot_wider()
pivot_longer()
将在列中列名(数值)转换到一列上。具体可见下图,将列变量转化为数据存在year列名中,相当于把数据变长(longer).函数主要参数:
cols选取的列; names_to 字符串,指定要从数据的列名中存储的数据创建的列的名称。 values_to 字符串,指定要从存储在单元格值中的数据创建的列的名称。 values_drop_na 如果为真,将删除value_to列中只包含NAs的行。
例子如上面例子:将
new_sp_m014
到newrel_f65
之间的列选取,汇总到key
列名中,值存在cases
列名中,并将含有缺失值的行进行删除。who1 <- who %>%
pivot_longer(
cols = new_sp_m014:newrel_f65,
names_to = 'key',
values_to = 'cases',
values_drop_na = T
)
当然还有一个和它相反功能的函数
poivot_wider()
。具体见下图,相当于把key
中的值变为列名,对应的values
数据转化到population
中.下面是简单的例子。library(tidyverse)
stocks <- tibble(
year = c(2015, 2015, 2016, 2016),
half = c( 1, 2, 1, 2),
return = c(1.88, 0.59, 0.92, 0.17)
)
stocks
我们将数据变宽,将
year
变为列名,对应在return
中的数据进行填充。stocks %>%
pivot_wider(names_from = year,values_from = return)
separate()
该函数可将字符进行分割,具体案例如上.
默认情况下,当
separate()
看到非字母数字字符(即不是数字或字母的字符)时,它将分割值。可以用里面的参数sep
。比如:sep='_'
。他还有一个功能,当sep=2
时,可通过第二个位置进行分割,使用在省份市级,等数据上。例如以下函数,其中into = c("century", "year")
将原始分割后的数据导入两个新列上,分别叫century
和year
。table3 %>%
separate(year, into = c("century", "year"), sep = 2)
注意:默认情况下,会转化成字符形式,你可以用参数
convert=T
,将数据转化最佳结构。unite
是
separate()
的反函数,这里做个补充。默认情况下,
sep='_'
如果我们不需要任何分隔符可以使用sep=''
。参考资料
tidy data论文: http://www.jstatsoft.org/v59/i10/paper
[2]《R for data science》: https://r4ds.had.co.nz/tidy-data.html
[3]《全球结核病报告》: http://www.who.int/tb/country/data/download/en/
欢迎关注我的公众号,点赞,在看,收藏~~~
阅读原文 最新评论
推荐文章
作者最新文章
你可能感兴趣的文章
Copyright Disclaimer: The copyright of contents (including texts, images, videos and audios) posted above belong to the User who shared or the third-party website which the User shared from. If you found your copyright have been infringed, please send a DMCA takedown notice to [email protected]. For more detail of the source, please click on the button "Read Original Post" below. For other communications, please send to [email protected].
版权声明:以上内容为用户推荐收藏至CareerEngine平台,其内容(含文字、图片、视频、音频等)及知识版权均属用户或用户转发自的第三方网站,如涉嫌侵权,请通知[email protected]进行信息删除。如需查看信息来源,请点击“查看原文”。如需洽谈其它事宜,请联系[email protected]。
版权声明:以上内容为用户推荐收藏至CareerEngine平台,其内容(含文字、图片、视频、音频等)及知识版权均属用户或用户转发自的第三方网站,如涉嫌侵权,请通知[email protected]进行信息删除。如需查看信息来源,请点击“查看原文”。如需洽谈其它事宜,请联系[email protected]。