4.2 基于tidyr包的数据整形

4.2.1 使用seperate()和unite()对数据进行拆分与合并

separate()函数可将一列拆分为多列,一般用于日志数据或日期时间型数据的拆分:
orders0 <- orders %>% 
              separate(col = orderid, 
                       into = c('center','year','product'), 
                       sep  = '-',
                       remove = FALSE)

这里用到了上文中提到的管道操作符:%>%。%>%是tidyverse中的函数,功能是用于实现将一个函数的输出传递给下一个函数的第一个参数。注意,变量传递给下一个函数的第一个参数,然后就不用写第一个参数了。seperate()函数的第一个参数是数据框;col参数是数据框中要进行拆分的列;into和seq指明了orderid列(订单id)以“-”为分隔符,被拆分为center、year和product三列。remove参数是逻辑变量,为真则删除进行操作的列。

unite()函数的作用跟seperate()相反,它用于将多列数据合并为一列。例如,我们将market(产品市场)和area(区域)合并为一列:

上述代码框中第一行是unite()的一般调用形式,…部分指明了要合并的列,可以同时指定多列。

4.2.2 使用gather()和spread()函数进行数据的长宽转变

直观来说,使用gather()和spread()函数处理数据会改变数据框的长度和宽度,所以我们称之为长宽转换。但是本质上讲,这两个函数改变的是数据表之间的连接关系,在某些情况下,这种改变会帮助我们更好的理解数据。

gather()函数类似于Excel中的数据透视的功能,能把一个变量名含有变量的二维表转换成一个规范的二维表。这句话从文字意思理解不够直观,但是结合实际案例就很容易理解:

orders2 <- orders %>%
  select(sales:shipcost) %>%
  gather(attribute, value, sales:shipcost)
orders2
## # A tibble: 256,450 x 2
##    attribute value
##    <chr>     <dbl>
##  1 sales      13.1
##  2 sales     252. 
##  3 sales     193. 
##  4 sales      35.4
##  5 sales      71.6
##  6 sales      56.1
##  7 sales      56.1
##  8 sales     345. 
##  9 sales      97.4
## 10 sales     342. 
## # ... with 256,440 more rows

为了使数据更加直观,我们首先将要转换的列筛选出来。select()函数是dplyr包的重要函数,用于选取数据框的列,我们将在下文进行介绍。我们选取了sales列到shipcost列的5列数据并将其转换为attribute、value两列。sales在原数据中作为变量名,但是转换之后成为了attribute列的变量,这就是上文提到的变量名含有变量。并不是所有变量进行长宽转换都具有实际意义,要具体问题具体分析。注意,仔细观察代码块中的%>%,%>%使得代码变得十分简洁,思考不使用管道操作符上述代码应该怎么写?

细心的读者会发现,gather()函数转化之后的数据会有比原数据更多的行,那么在代码框中的gather()是如何起作用 的呢?观察下面的代码块和代码输出的结果:

orders2 <- orders %>%
  select(sales:shipcost) %>%
  gather(attribute, value, sales:shipcost)
orders2
## # A tibble: 256,450 x 2
##    attribute value
##    <chr>     <dbl>
##  1 sales      13.1
##  2 sales     252. 
##  3 sales     193. 
##  4 sales      35.4
##  5 sales      71.6
##  6 sales      56.1
##  7 sales      56.1
##  8 sales     345. 
##  9 sales      97.4
## 10 sales     342. 
## # ... with 256,440 more rows

我们可以在Rstudio中使用View(orders2)命令查看完整的数据框。我们可以发现数据框中其它列的数据被保存,并且进行了复制以适应数据框的长度变化。

gather()用于将宽数据转换可长数据,spread()函数则用于将长数据转换为宽数据。例如,我们使用sprad()函数将刚刚合并的attribute列和value列拆分为原数据: