【数据整理】R用tidyr包进行数据操作
大家好!在这篇文章中,我会向你们展示如何用tidyr包进行数据操作。Tidyr包是由Hadely Wickham先生创建的,这个包提高了整理原始数据的效率,而且通常在连接词之间使用。我们常说当把每个列都看作是一个变量,而每行都当作是它的函数的时候,这时我们就说这些数据需要进行整理。
下面我会列举tidyr包的4个常用的函数及其用途:
gather-把宽度较大的数据转换成一个更长的形式,它类比于从reshape2包中融合函数的功能。
spread-把长的数据转换成一个更宽的形式,它类比于从reshape2包中铸造函数的功能。
unite-把2个或多个列组合成一个单列。
separate-把一个列分解成两个或多个列。
我会从数据集库中调用mtcars数据集。如果你对这个数据集感到陌生,那我现在先给你看一下它是怎样的:
library(tidyr)
library(dplyr)
head(mtcars)
mpg cyl disp hp drat wt qsec vs am gear carb
MazdaRX4 21.0 6 160110 3.90 2.620 16.46 0 1 4 4
MazdaRX4 Wag 21.0 6 160110 3.90 2.875 17.02 0 1 4 4
Datsun710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet4 Drive 21.4 6 258110 3.08 3.215 19.44 1 0 3 1
HornetSportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225105 2.76 3.460 20.22 1 0 3 1
现在我们从mtcars数据集中查看一下car变量里出现的名字,这样我们更容易进行数据操作:
mtcars$car <- rownames(mtcars)
mtcars <- mtcars[, c(12, 1:11)]
gather
gather的形式如下(参照帮助文档):
gather takesthe form (from the help file):
gather(data, key, value, ..., na.rm = FALSE, convert = FALSE)
这里,……展示了所有要聚集的列的大致规格。
我们可以复制一下先前的脚本,看看它融合了什么东西。
mtcarsNew <- mtcars="">% gather(attribute, value, -car)
head(mtcarsNew)
car attribute value
1 Mazda RX4 mpg 21.0
2 Mazda RX4 Wag mpg 21.0
3 Datsun 710 mpg 22.8
4 Hornet 4 Drive mpg 21.4
5 Hornet Sportabout mpg 18.7
6 Valiant mpg 18.1
tail(mtcarsNew)
car attribute value
347 Porsche 914-2 carb 2
348 Lotus Europa carb 2
349 Ford Pantera L carb 4
350 Ferrari Dino carb 6
351 Maserati Bora carb 8
352 Volvo 142E carb 2
正如你看到的那样,它把出了car以外的所有列都聚集起来,然后各自地把它们名字都放在各自的属性和相应的值的列中。
tidyr包中有一样最好的就是你可以只把已经确认好的列结合在一起而其它的列可以原封不动。如果我们想把从mpg到gear的所有列结合起来并除去carb和car的话,我们可以按一下的做法来做:
mtcarsNew <- mtcars="">% gather(attribute, value, mpg:gear)
head(mtcarsNew)
car carb attribute value
1 Mazda RX4 4 mpg 21.0
2 Mazda RX4 Wag 4 mpg 21.0
3 Datsun 710 1 mpg 22.8
4 Hornet 4 Drive 1 mpg 21.4
5 Hornet Sportabout 2 mpg 18.7
6 Valiant 1 mpg 18.1
spread
spread的形式如下(来自于帮助文档):
spread takesthe form(from the help file):
spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE)
我们可以看一下它铸造了什么:
mtcarsSpread <- mtcarsnew="">% spread(attribute, value)
head(mtcarsSpread)
car carb mpg cyl disp hp drat wt qsec vs am gear
1 AMC Javelin 2 15.2 8 304 150 3.15 3.435 17.30 0 0 3
2 Cadillac Fleetwood 4 10.4 8 472 205 2.93 5.250 17.98 0 0 3
3 Camaro Z28 4 13.3 8 350 245 3.73 3.840 15.41 0 0 3
4 Chrysler Imperial 4 14.7 8 440 230 3.23 5.345 17.42 0 0 3
5 Datsun 710 1 22.8 4 108 93 3.85 2.320 18.61 1 1 4
6 Dodge Challenger 2 15.5 8 318 150 2.76 3.520 16.87 0 0 3
Unite
Unite的形式如下(来自于帮助文档):
unite(data, col, ..., sep = "_", remove = TRUE)
这里,….展示了要结合的列,而col则展示了要添加的列。
现在我们创建一下假数据:
set.seed(1)
date <- as.Date('2016-01-01') + 0:14
hour <- sample(1:24, 15)
min <- sample(1:60, 15)
second <- sample(1:60, 15)
event <- sample(letters, 15)
data <- data.frame(date, hour, min, second, event)
data
date hour min second event
1 2016-01-01 7 30 29 u
2 2016-01-02 9 43 36 a
3 2016-01-03 13 58 60 l
4 2016-01-04 20 22 11 q
5 2016-01-05 5 44 47 p
6 2016-01-06 18 52 37 k
7 2016-01-07 19 12 43 r
8 2016-01-08 12 35 6 i
9 2016-01-09 11 7 38 e
10 2016-01-10 1 14 21 b
11 2016-01-11 3 20 42 w
12 2016-01-12 14 1 32 t
13 2016-01-13 23 19 52 h
14 2016-01-14 21 41 26 s
15 2016-01-15 8 16 25 o
现在,我们把data, hour, min和second这几个列整合成一个叫datatime(时间日期)的列。通常情况下,R里的时间的形式一般都是Year-Month-Day Hour:Min:Second(年-月-日 小时:分钟:秒):
dataNew <- data="">%
unite(datehour, date, hour, sep = ' ') %>%
unite(datetime, datehour, min, second, sep = ':')
dataNew
datetime event
1 2016-01-01 7:30:29 u
2 2016-01-02 9:43:36 a
3 2016-01-03 13:58:60 l
4 2016-01-04 20:22:11 q
5 2016-01-05 5:44:47 p
6 2016-01-06 18:52:37 k
7 2016-01-07 19:12:43 r
8 2016-01-08 12:35:6 i
9 2016-01-09 11:7:38 e
10 2016-01-10 1:14:21 b
11 2016-01-11 3:20:42 w
12 2016-01-12 14:1:32 t
13 2016-01-13 23:19:52 h
14 2016-01-14 21:41:26 s
15 2016-01-15 8:16:25 o
separate
separate的形式如下(来自帮助文档):
separate takesthe form (from the help file):
separate(data, col, into, sep = "[^[:alnum:]]+", remove = TRUE,
convert = FALSE, extra = "warn", fill = "warn", ...)
我们可以根据之前在进行separate操作时所创建的原始数据进行操作,详细如下:
data1 <- datanew="">%
separate(datetime, c('date', 'time'), sep = ' ') %>%
separate(time, c('hour', 'min', 'second'), sep = ':')
data1
date hour min second event
1 2016-01-01 07 30 29 u
2 2016-01-02 09 43 36 a
3 2016-01-03 13 59 00 l
4 2016-01-04 20 22 11 q
5 2016-01-05 05 44 47 p
6 2016-01-06 18 52 37 k
7 2016-01-07 19 12 43 r
8 2016-01-08 12 35 06 i
9 2016-01-09 11 07 38 e
10 2016-01-10 01 14 21 b
11 2016-01-11 03 20 42 w
12 2016-01-12 14 01 32 t
13 2016-01-13 23 19 52 h
14 2016-01-14 21 41 26 s
15 2016-01-15 08 16 25 o
它首先把datetime这个列分解成date和time,然后又把time分解成hour, min和second。
那么,我已经到了文章的结尾。如果你还有什么问题要反馈,你可以随时进行留言或者来twitter找我。
原文链接:http://www.r-bloggers.com/data-manipulation-with-tidyr/
作者:何品言,热爱英语何数据科学。
严禁修改,可以转载,但是请注明出处(数据人网)和链接http://shujuren.org/index.php/Article/update/aid/135。
更多精彩内容,请点击阅读原文。
数据人网(http://shujuren.org),数据人学习、交流和分享的家园,专注于从数据中学习,努力发觉数据之洞见,积极利用数据之价值。为“让人懂数据、用数据”之使命坚持做点事情。大家可以来投稿,做分享和传播,可以给反馈。您有什么想法,请反馈给我们,谢谢。数据人网,我们共建和共享。
请关注“恒诺新知”微信公众号,感谢“R语言“,”数据那些事儿“,”老俊俊的生信笔记“,”冷🈚️思“,“珞珈R”,“生信星球”的支持!