R语言基础系列:
- R语言基础1--R数据格式:.rds和.rda的区别
- R语言基础2--数据排序与长宽型数据的转换
- R语言基础3--tidyverse包总结
- R语言基础4--dplyr包的函数及用法
tidyr包的应用
- tidyr主要提供了一个类似Excel中数据透视表(pivot table)的功能。
gather()
和spread()
函数将数据在长格式和宽格式之间相互转化,应用在比如稀疏矩阵和稠密矩阵之间的转化。(用于数据框 )separate()
和union()
方法提供了数据分组拆分、合并的功能,应用在nominal数据的转化上。(用于数据框 )- tidyr还提供一些简单的缺失值处理方法。
# 查看这个包的网页说明书
browseVignettes('tidyr')
1. gather实现wide 到 long 转换
类似reshape2包中melt函数的功能
- 语法
gather(data, key = "key", value = "value",..., na.rm = FALSE, convert = FALSE, factor_key = FALSE)
- 参数
参数 | 含义 |
---|---|
data | 需要被转换的宽形数据框 |
key | 将原数据框中的所有列赋给一个新变量key |
value | 将原数据框中的所有值赋给一个新变量value |
… | 可以指定哪些列聚到同一列中,可用于选择两列之间的所有列col1:coln, 排除列-coln |
na.rm | 是否删除缺失值,默认为FALSE |
convert | 为TRUE时会自动在key列上使用type.convert函数,默认值为FALSE |
factor_key | FALSE时key值为字符向量,TRUE时key值为factor类型 |
- 使用
library(tidyr)
library(dplyr)
stocks <- tibble(
time = as.Date('2009-01-01') + 0:9,
X = rnorm(10, 0, 1),
Y = rnorm(10, 0, 2),
Z = rnorm(10, 0, 4)
)
stocks
# A tibble: 10 x 4
# time X Y Z
#
# 1 2009-01-01 -0.326 3.32 5.84
# 2 2009-01-02 0.410 3.99 -1.97
# 3 2009-01-03 -0.344 -0.394 4.09
# 4 2009-01-04 -1.11 1.12 -5.43
# 5 2009-01-05 -0.374 0.303 0.336
# 6 2009-01-06 2.72 1.38 -4.86
# 7 2009-01-07 0.416 3.39 -1.27
# 8 2009-01-08 2.31 1.25 -2.13
# 9 2009-01-09 -0.0643 4.87 1.37
# 10 2009-01-10 -0.0232 2.73 1.38
gather(stocks, "stock", "price", -time)
stocks %>% gather("stock", "price", -time)
# A tibble: 30 x 3
# time stock price
#
# 1 2009-01-01 X -0.326
# 2 2009-01-02 X 0.410
# 3 2009-01-03 X -0.344
# 4 2009-01-04 X -1.11
# 5 2009-01-05 X -0.374
# 6 2009-01-06 X 2.72
# 7 2009-01-07 X 0.416
# 8 2009-01-08 X 2.31
# 9 2009-01-09 X -0.0643
# 10 2009-01-10 X -0.0232
# … with 20 more rows
2. spread实现long 到wide转换(类似reshape2包中cast函数的功能)
- 语法
spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE, sep = NULL)
- 参数
参数 | 含义 |
---|---|
data | 为需要转换的长形data.frame |
key | 设置需要扩宽的类别变量 |
value | 设置需要扩宽的变量的度量值 |
fill | 对于缺失值,可将fill的值赋值给被转型后的缺失值 |
convert | 为TRUE时会自动在新列上使用type.convert函数,其中as.is = TRUE,默认值为FALSE |
drop | 为FALSE保留factor的level,使用fill的值填充missing的值 |
sep | 为默认值NULL时,新列名使用key中的值,非NULL时,新列名为 |
- 使用
library(dplyr)
stocks <- data.frame(
time = as.Date('2009-01-01') + 0:9,
X = rnorm(10, 0, 1),
Y = rnorm(10, 0, 2),
Z = rnorm(10, 0, 4)
)
stocks
# A tibble: 10 x 4
# time X Y Z
#
# 1 2009-01-01 -0.326 3.32 5.84
# 2 2009-01-02 0.410 3.99 -1.97
# 3 2009-01-03 -0.344 -0.394 4.09
# 4 2009-01-04 -1.11 1.12 -5.43
# 5 2009-01-05 -0.374 0.303 0.336
# 6 2009-01-06 2.72 1.38 -4.86
# 7 2009-01-07 0.416 3.39 -1.27
# 8 2009-01-08 2.31 1.25 -2.13
# 9 2009-01-09 -0.0643 4.87 1.37
# 10 2009-01-10 -0.0232 2.73 1.38
stocksm <- stocks %>% gather(stock, price, -time)
head(stocksm)
# time stock price
# 1 2009-01-01 X 0.8126651
# 2 2009-01-02 X -0.3387208
# 3 2009-01-03 X -0.6778238
# 4 2009-01-04 X 0.3713640
# 5 2009-01-05 X -1.5019406
# 6 2009-01-06 X -0.8858434
stocksm %>% spread(stock, price)
# time X Y Z
# 1 2009-01-01 0.81266513 -2.21316283 7.9265756
# 2 2009-01-02 -0.33872080 3.52921094 -1.2218472
# 3 2009-01-03 -0.67782385 -1.82005963 1.2567876
# 4 2009-01-04 0.37136402 -1.22181178 -0.2963697
# 5 2009-01-05 -1.50194061 -1.56952607 3.1274926
# 6 2009-01-06 -0.88584341 5.17005476 -10.9974695
# 7 2009-01-07 0.22308469 0.07021010 -3.2228298
# 8 2009-01-08 0.08303945 -5.20103460 -0.1731917
# 9 2009-01-09 -0.58188891 -0.47327216 0.7320103
# 10 2009-01-10 -0.33931690 0.01911578 -7.2114319
stocksm %>% spread(time, price)
# stock 2009-01-01 2009-01-02 2009-01-03 2009-01-04 2009-01-05 2009-01-06
# 1 X 0.8126651 -0.3387208 -0.6778238 0.3713640 -1.501941 -0.8858434
# 2 Y -2.2131628 3.5292109 -1.8200596 -1.2218118 -1.569526 5.1700548
# 3 Z 7.9265756 -1.2218472 1.2567876 -0.2963697 3.127493 -10.9974695
# 2009-01-07 2009-01-08 2009-01-09 2009-01-10
# 1 0.2230847 0.08303945 -0.5818889 -0.33931690
# 2 0.0702101 -5.20103460 -0.4732722 0.01911578
# 3 -3.2228298 -0.17319172 0.7320103 -7.21143190
3. unite 可将多列按指定分隔符合并为一列
- 语法
unite(data, col, ..., sep = "_", remove = TRUE)
- 参数
参数 | 含义 |
---|---|
data | 为数据框 |
col | 被组合的新列名称 |
… | 指定哪些列需要被组合, 可用于选择两列之间的所有列col1:coln, 排除列-coln |
sep | 组合列之间的连接符,默认为下划线 |
remove | 是否删除被组合的列 |
- 使用
df <- expand_grid(x = c("a", NA), y = c("b", NA))
df
# A tibble: 4 x 2
# x y
#
# 1 a b
# 2 a NA
# 3 NA b
# 4 NA NA
df %>% unite("z", x:y, remove = FALSE) #若remove = TRUE,则不保留x和y列
# A tibble: 4 x 3
# z x y
#
# 1 a_b a b
# 2 a_NA a NA
# 3 NA_b NA b
# 4 NA_NA NA NA
df %>% unite("z", x:y, na.rm = TRUE, remove = FALSE)
# A tibble: 4 x 3
# z x y
#
# 1 "a_b" a b
# 2 "a" a NA
# 3 "b" NA b
# 4 "" NA NA
4. separate分割一列为多列
类似于reshape2中的colsplit函数
- 语法
separate(data, col, into, sep = "[^[:alnum:]]+", remove = TRUE, convert = FALSE, extra = "warn", fill = "warn", ...)
- 参数
参数 | 含义 |
---|---|
data | 为数据框 |
col | 需要被拆分的列 |
into | 新建的列名,为字符串向量 |
sep | 被拆分列的分隔符 |
remove | 是否删除被分割的列 |
convert | 为TRUE时会自动在新列上使用type.convert函数,其中as.is = TRUE,默认值为FALSE |
extra | 当分割成的列多于length(into)时,"warn"(默认值) 发出警告并删除多余值,"drop"直接删除多余值,"merge"仅分割length(into)次 |
fill | 当分割成的列少于length(into)时,"warn"(默认值) 发出警告并从右侧填充缺失值,"right"直接从右侧填充缺失值,"left"直接从左侧填充缺失值 |
- 使用
library(dplyr)
df <- data.frame(x = c(NA, "a.b", "a.d", "b.c"))
#分割为两列,保留NA值
df %>% separate(x, c("A", "B"))
df <- data.frame(x = c("a", "a b", "a b c", NA))
#分割为两列,发出warning并删除多余的列,缺失的列从右以NA填充
df %>% separate(x, c("a", "b"))
#分割为两列,直接删除多余的列,缺失的列从右以NA填充
df %>% separate(x, c("a", "b"), extra = "drop", fill = "right")
#分割两次(设置的列为两列),缺失的列从左以NA填充
df %>% separate(x, c("a", "b"), extra = "merge", fill = "left")
df <- data.frame(date = c("2017-03-08 01:20:20", "2017-03-09 02:30:30", "2017-03-10 03:40:40"))
#分割为year,month,day,hour,minute,second六列
df %>%
separate(date, c("day", "time"), sep = " ") %>%
separate(day, c("year", "month", "day"), sep = "-") %>%
separate(time, c("hour", "minute", "second"), sep = ":")
与separate不同的是extract使用正则表达式regex提取需要分割的列,当输入为NA或者不能匹配regex时,输出为NA。
extract(data, col, into, regex = "([[:alnum:]]+)", remove = TRUE, convert = FALSE, ...)
library(dplyr)
df <- data.frame(x = c(NA, "a.b", "a.d", "b.c"))
#分割为两列,regex匹配要分割的列
df %>% extract(x, c("a", "b"), regex = "([a-d]+).([a-d]+)")
df %>% extract(x, c("A", "B"), "([[:alnum:]]+).([[:alnum:]]+)")
#分割为两列,regex匹配要分割的列,不能匹配列的输出为NA
df %>% extract(x, c("a", "b"), regex = "([a-d]+).([a-c]+)")
#分割为一列
df %>% extract(x, c("a"), regex = "([a-d]+)")
df %>% extract(x, c("a"))
separate_rows用于将列分割为多行,”... ”用于设置需要分割的列,sep用于设置分隔符,需要注意的是分割多个列时,每个列分割成的行数必须要一致。
separate_rows(data, ..., sep = "[^[:alnum:].]+", convert = FALSE)
library(dplyr)
df <- data.frame(
x = 1:3,
y = c("a", "d,e,f", "g,h"),
z = c("1", "2,3,4", "5,6"),
stringsAsFactors = FALSE
)
#分割y和z列,转换为行
separate_rows(df, y, z, convert = TRUE)
5. 缺失值处理
tidyr包提供了简单的缺失值处理方法,包括替换,填充,删除等
- 使用给定值替换每列的缺失值
replace_na(data, replace = list(), ...)
# data:为数据框
# replace:替换值用于替换每个列中NA
library(dplyr)
df <- tibble(x = c(1, 2, NA), y = c("a", NA, "b"))
#以0替换x中的NA,以unknown替换y中的NA
df %>% replace_na(list(x = 0, y = "unknown"))
- 以前一个值填充缺失值,默认自上向下填充
fill(data, ..., .direction = c("down", "up"))
# data:为数据框
# …:指定需要被填充的列, 可用于选择两列之间的所有列col1:coln, 排除列-coln
# .direction :填充的方向,默认为down,自上向下填充
df <- data.frame(x = 1:5, y = c(10, NA, 15, NA, 20))
#自上向下替换NA值
df %>% fill(y)
df %>% fill(y, .direction = "down")
#自下向上替换NA值
df %>% fill(y, .direction = "up")
- 填充以创建完整的序列值向量
full_seq(x, period, tol = 1e-06)
# x:数值向量
# period:观测值间的间隔,并检测现有数据是否与这个间隔匹配,,不匹配时报错
#返回序列1:6
full_seq(c(1, 2, 4, 6), 1)
#period值与原数据间隔不匹配,报错Error: `x` is not a regular sequence.
full_seq(c(1, 2, 4, 6), 2)
#返回序列1:13,间隔为2
full_seq(c(1, 5, 9, 13), 2)
- 删除包含缺失值的行
drop_na(data, ...)
# data:为数据框
# …:指定需要被填充的列, 可用于选择两列之间的所有列col1:coln, 排除列-coln
df <- data_frame(x = c(1, 2, NA), y = c("a", NA, "b"))
#删除变量x中NA对应的行
df %>% drop_na(x)
#删除变量y中NA对应的行
df %>% drop_na(y)
#未设置列,删除变量x和y中NA对应的行
df %>% drop_na()
- 转换隐式的缺失值为显式的
complete(data, ..., fill = list())
# data:为数据框
# …:指定需要扩展的列,每个输入列都作为一个独立的参数用于扩展数据框。其中使用crossing或者直接输入列作为参数时,会使用每个列中的元素进行扩展,即使生成的组合在原数据框中不存在;而使用nesting函数时,返回的每个列元素的组合必须在原数据框中存在。
# fill:用于设置填充值以替换NA
df <- data_frame(
group = c(1:2, 1),
item_id = c(1:2, 2),
item_name = c("a", "b", "b"),
value1 = 1:3,
value2 = 4:6
)
#以item_id和item_name中的每个元素扩展原数据框, 组合后的缺失值以NA代替
df %>% complete(item_id, item_name)
df %>% complete(crossing(item_id, item_name))
#以item_id和item_name中的每个元素扩展原数据框, 并以给定值替换缺失值
df %>% complete(item_id, item_name, fill = list(group = 0, value1 = 0, value2 = 0))
#以item_id和item_name中的每个元素扩展原数据框,只返回原数据框中存在的组合
df %>% complete(nesting(item_id, item_name))
#保留group,以item_id和item_name中的每个元素扩展原数据框,只返回原数据框
#中item_id和item_name存在的组合
df %>% complete(group, nesting(item_id, item_name))
df %>% complete(group, nesting(item_id, item_name), fill = list(value1 = 0, value2 = 0))
#保留group,以item_id和item_name中的每个元素扩展原数据框,返回所有item_id
#和item_name存在的组合
df %>% complete(group, crossing(item_id, item_name))
df %>% complete(group, crossing(item_id, item_name), fill = list(value1 = 0, value2 = 0))
参考:https://blog.csdn.net/wltom1985/article/details/107902563