大家好!在這篇文章中,我會向你們展示如何用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),數據人學習、交流和分享的家園,專注於從數據中學習,努力發覺數據之洞見,積極利用數據之價值。為「讓人懂數據、用數據」之使命堅持做點事情。大家可以來投稿,做分享和傳播,可以給反饋。您有什麼想法,請反饋給我們,謝謝。數據人網,我們共建和共享。