4.2 基于tidyr包的数据整形
4.2.1 使用seperate()和unite()对数据进行拆分与合并
separate()函数可将一列拆分为多列,一般用于日志数据或日期时间型数据的拆分:<- orders %>%
orders0 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中的数据透视的功能,能把一个变量名含有变量的二维表转换成一个规范的二维表。这句话从文字意思理解不够直观,但是结合实际案例就很容易理解:
<- orders %>%
orders2 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()是如何起作用 的呢?观察下面的代码块和代码输出的结果:
<- orders %>%
orders2 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列拆分为原数据: