本篇介绍的函数来自tidyr
工具包,它也是tidyverse
系列工具包的重要组成部分。
在之前的推文里,小编介绍了一些数据批量化处理的方法,如下(点击文字可直接跳转):
在这些推文中,为了方便介绍向量化/批量化操作的特点,小编举的都是一些比较简单的例子,而在实际的数据处理中,通过结合数据的嵌套化操作,apply()
族、map()
族等函数可以实现更复杂场景的批量化运算。
数据嵌套化
nest()
函数的语法结构如下:
nest(.data, ..., .names_sep = NULL)
data:输入对象(数据框结构);
...:嵌套语句。
数据嵌套化和数据分组的区别:
数据分组(
dplyr::group_by()
函数):建立分组索引,但不会实际改变数据框的大小(行数和列数);数据嵌套(
tidyr::nest()
函数):将同一分组对应的其他变量信息嵌套在一个list中,再作为数据框的一个元素,会改变数据框的大小。
以上介绍可能有些抽象,下面通过实例进行介绍它的两种用法。
单独使用
library(tidyverse)
data("iris")
nested.iris <- iris %>%
nest(petal = c(Petal.Length, Petal.Width),
sepal = c(Sepal.Length, Sepal.Width))
通过以上代码,
Petal.Length
和Petal.Width
变量就被嵌套成petal
变量了,Sepal.Length
和Sepal.Width
变量则被嵌套成了sepal
变量;未参与嵌套的变量自动作为分组变量。
嵌套前:
嵌套后:
只有
Species
变量未参与嵌套操作,因此自动被作为分组变量。
通过点击上图中红色框内的按钮,可以查看被嵌套的数据,如下图:
可以看出,被嵌套的数据也是一个完整的数据框结构。
与group_by()
函数连用
nest()
函数还可以跟在group_by()
函数之后使用,这种用法更为常用。示例如下:
nested.iris2 <- iris %>%
group_by(Species) %>%
nest()
输出对象如下:
嵌套后批量化运算
数据嵌套化使得每组数据独占一行,有利于进行批量化操作,这一点在介绍“线性模型之亚组模型”中已有介绍,这里再重复一下示例:
model <- mtcars%>%
group_by(cyl) %>%
nest() %>%
mutate(model = map(data, ~lm(mpg ~ wt + qsec,
data = .x)))
去嵌套化
同取消分组操作一样,也存在取消嵌套化操作,相应函数为unnest()
:
unnest(data, cols, ...,
keep_empty = FALSE,
ptype = NULL,
names_sep = NULL,
names_repair = "check_unique")
该函数使用起来也非常简单,默认取消所有嵌套结构。示例如下:
unnested.iris <- unnest(nested.iris)
输出对象与嵌套前的对象一样。
仅取消部分嵌套结构,需指定cols
参数。示例如下:
unnested.iris2 <- unnest(nested.iris, cols = c(petal))
与unnest()
函数相关的还有另外两个函数:unnest_longer()
、unnest_wider()
,这两个函数必须指定col
参数(注意参数名是col
而不是cols
)。
unnest_longer()
函数输出对象与unnest()
相似,但数据结构存在区别。示例如下:
unnested.iris3 <- unnest_longer(nested.iris, col = petal)
上图虽然看起来和unnest()
函数的输出对象一样,但它实际上只有3个变量:
names(unnested.iris3)
## [1] "Species" "petal" "sepal"
unnest_wider()
函数生成的是“宽”数据。示例如下:
unnested.iris4 <- unnest_wider(nested.iris, col = petal)