Data Summarisation

27 数据整理

tidyverse系统

假设数据以tibble格式保存。 数据集如果用于统计与绘图, 需要满足一定的格式要求, (Wickham 2014)称之为整洁数据(tidy data), 基本要求是每行一个观测, 每列一个变量, 每个单元格恰好有一个数据值。

数据集经常需要选行子集、选列子集、排序、定义新变量、横向合并、长宽转换等操作, 而且经常会用若干个连续的操作分步处理, magrittr包的管道运算符%>%特别适用于这种分步处理。

dplyr包和tidyr包定义了一系列“动词”, 可以用比较自然的方式进行数据整理。 较复杂的分组操作还可以利用purrr包的map类函数。

为了使用这些功能,可以载入tidyverse包, 则magrittr包,readr包,dplyr包和tidyr包都会被自动载入:

library(tidyverse)

先前载入的d.class数据框有19个观测值,有5个变量。

R的NHANES扩展包提供了一个规模更大的示例数据框NHANES, 可以看作是美国扣除住院病人以外的人群的一个随机样本, 有10000个观测,有76个变量, 主题是个人的健康与营养方面的信息。 仅作为教学使用而不足以作为严谨的科研用数据。 原始数据的情况详见http://www.cdc.gov/nchs/nhanes.htm。 载入NHANES数据框:

# install.packages("NHANES")
library(NHANES)
data(NHANES)
print(dim(NHANES))
## [1] 10000 76
print(names(NHANES))

用filter()选择行子集

dplyr包的filter()函数可以按条件选出符合条件的行组成的子集。 下例从d.class中选出年龄在13岁和13岁以上的男生:

d.class %>%
filter(sex == "M", age>=13) %>%
knitr::kable()
name sex age height weight
Alfred M 14 69.0 112.5
Duke M 14 63.5 102.5
Guido M 15 67.0 133.0
Jeffrey M 13 62.5 84.0
Philip M 16 72.0 150.0
William M 15 66.5 112.0

filter()函数第一个参数是要选择的数据框, 后续的参数是条件, 这些条件是需要同时满足的, 另外, 条件中取缺失值的观测自动放弃。

filter()会自动舍弃行名, 如果需要行名只能将其转换成数据框的一列。

filter()的结果为行子集数据框。

按行序号选择行子集

R基本函数的数据选择:
head(x, n):取x的前n行数据;
``tail(x,n)`:取x的后n行数据。

载入tidyverse包, 则magrittr包,readr包,dplyr包和tidyr包都会被自动载入
magrittr包的管道运算符%>%

library(tidyverse)
d.class %>%
head(5) %>%
knitr::kable()
name sex age height weight
Alice F 13 56.5 84.0
Becka F 13 65.3 98.0
Gail F 14 64.3 90.0
Karen F 12 56.3 77.0
Kathy F 12 59.8 84.5

dplyr包的函数slice(.data, ...)可以用来选择指定序号的行子集, 正的序号表示保留,负的序号表示排除。如:

# 数据类型与原来的保持一致
slice(d.class,c(2,4)) %>%
knitr::kable()
name sex age height weight
Becka F 13 65.3 98
Karen F 12 56.3 77

sample_n()对观测随机抽样

dplyr包的sample_n(tbl, size)函数可以从数据集tbl中随机无放回抽取size行,如:

sample_n(d.class, size = 5) %>%
knitr::kable()
name sex age height weight
Karen F 12 56.3 77.0
Philip M 16 72.0 150.0
Sharon F 15 62.5 112.5
Gail F 14 64.3 90.0
Mary F 15 66.5 112.0

sample_n()中加选项replace=TRUE可以变成有放回抽样。 可以用weight选项指定数据框中的一列作为抽样权重, 进行不等概抽样。

distinct()去除重复行

# 筛选出性别与年龄的所有不同组合
d.class %>%
distinct(sex, age) %>%
knitr::kable()
sex age
F 13
F 14
F 12
F 15
F 11
M 14
M 15
M 12
M 13
M 16
M 11

如果希望保留数据框中其它变量, 可以加选项.keep_all=TRUE。

# 筛选出性别与年龄的所有不同组合
d.class %>%
distinct(sex, age, .keep_all = T) %>%
knitr::kable()

.keep_all= T选项会保留数据中满足条件第一个值。

name sex age height weight
Alice F 13 56.5 84.0
Gail F 14 64.3 90.0
Karen F 12 56.3 77.0
Mary F 15 66.5 112.0
Sandy F 11 51.3 50.5
Alfred M 14 69.0 112.5
Guido M 15 67.0 133.0
James M 12 57.3 83.0
Jeffrey M 13 62.5 84.0
Philip M 16 72.0 150.0
Thomas M 11 57.5 85.0
# 查看NHANES数据框中ID与SurveyYr的组合的不同值的个数
NHANES %>%
distinct(ID, SurveyYr) %>%
nrow()
## [1] 6779
# 这个结果提示有些人在某一调查年中有多个观测。

drop_na()去除指定的变量有缺失值的行

在进行统计建模时, 通常需要用到的因变量和自变量都不包含缺失值。 tidyr包的drop_na()函数可以对数据框指定一到多个变量, 删去指定的变量有缺失值的行。 不指定变量时有任何变量缺失的行都会被删去。

将NHANES中所有存在缺失值的行删去后数出保留的行数, 原来有10000行:

NHANES %>%
drop_na() %>%
nrow()
## [1] 0

这表示所有行搜有缺失值。
而对列数怎没有影响:

# 显示列数
ncol(NHANES)
## [1] 76
ncol(drop_na(NHANES))
## [1] 76

NHANES数据集的数据量比较大-10000行,不方便显示,下面对d.class数据进行改造,使其产生缺失值,然后再用drop_na()进行缺失值的过滤

# 将第一行第一列的值改为NA,并将数据保存为d.class.NA
d.class.NA <- d.class
d.class.NA[1,1] <- NA
# 查看前两行数据
view(head(d.class.NA,2))

使用drop_na()过滤数据:

# 查看前4行数据
head(d.class.NA,4) %>%
knitr::kable()
name sex age height weight
NA F 13 56.5 84
Becka F 13 65.3 98
Gail F 14 64.3 90
Karen F 12 56.3 77
# 使用drop_na()过滤数据
# 并查看前3行数据
d.class.NA %>%
drop_na() %>%
head(.,3) %>%
knitr::kable()
name sex age height weight
Becka F 13 65.3 98
Gail F 14 64.3 90
Karen F 12 56.3 77

可以看到第一行数据已经去除。