tidyr包:进阶版reshape2
tidyr包
tidyr是reshape2的进阶版本,它提供了更加定制化的数据整洁功能,用于数据的合并、拆分以及长宽格式的转化
主要涉及的操作:
- 缺失值的补充
- 长形表变宽形表,宽形表变长形表
- gather-把宽度较大的数据转换成一个更长的形式,它类比于从reshape2包中melt函数的功能
- spread-把长的数据转换成一个更宽的形式,它类比于从reshape2包中cast函数的功能
- 列分割与列合并
- separate-将一列按分隔符分割为多列
- unite-将多列按指定分隔符合并为一列
常见用法
数据准备
> library(tidyr)> library(tibble)> mtcars <- rownames_to_column(mtcars, var ='car')> head(mtcars)car mpg cyl disp hp drat wt qsec vs am gear carb1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 42 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 43 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 14 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 15 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 26 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
数据重构(Reshape Data)
gather—宽数据转为长数据
gather(data, key, value, …, na.rm = FALSE, convert = FALSE) data:需要被转换的宽形表 key:将原数据框中的所有列赋给一个新变量key value:将原数据框中的所有值赋给一个新变量value …:可以指定哪些列聚到同一列中 na.rm:是否删除缺失值
> mtcarsNew <- gather(mtcars, attribute, value, -car) # 除了car列外,其余列聚合成两列,分别命名为attribute和value> head(mtcarsNew)car attribute value1 Mazda RX4 mpg 21.02 Mazda RX4 Wag mpg 21.03 Datsun 710 mpg 22.84 Hornet 4 Drive mpg 21.45 Hornet Sportabout mpg 18.76 Valiant mpg 18.1
tidyr很好的一点是可以只gather若干列而其他列保持不变,这点要比melt更加灵活
> mtcarsNew <- mtcars %>% gather(attribute, value, mpg:gear)> head(mtcarsNew)car carb attribute value1 Mazda RX4 4 mpg 21.02 Mazda RX4 Wag 4 mpg 21.03 Datsun 710 1 mpg 22.84 Hornet 4 Drive 1 mpg 21.45 Hornet Sportabout 2 mpg 18.76 Valiant 1 mpg 18.1
spread—长数据转为宽数据
spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE) data:为需要转换的长形表 key:需要将变量值拓展为字段的变量 value:需要分散的值 fill:对于缺失值,可将fill的值赋值给被转型后的缺失值
> mtcarsSpread <- mtcarsNew %>% spread(attribute, value) # 返回原来的数据格式> head(mtcarsSpread)car carb am cyl disp drat gear hp mpg qsec vs wt1 AMC Javelin 2 0 8 304 3.15 3 150 15.2 17.30 0 3.4352 Cadillac Fleetwood 4 0 8 472 2.93 3 205 10.4 17.98 0 5.2503 Camaro Z28 4 0 8 350 3.73 3 245 13.3 15.41 0 3.8404 Chrysler Imperial 4 0 8 440 3.23 3 230 14.7 17.42 0 5.3455 Datsun 710 1 1 4 108 3.85 4 93 22.8 18.61 1 2.3206 Dodge Challenger 2 0 8 318 2.76 3 150 15.5 16.87 0 3.520
使用spread函数后,数据的排列顺序有一定的调整
数据分割与合并
unite—多列合并为一列
unite(data, col, …, sep = “_”, remove = TRUE) data:为数据框 col:被组合的新列名称 …:指定哪些列需要被组合 sep:组合列之间的连接符,默认为下划线 remove:是否删除被组合的列
> date <- as.Date('2019-04-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)> datadate hour min second event1 2019-04-01 7 30 29 u2 2019-04-02 9 43 36 a3 2019-04-03 13 58 60 l4 2019-04-04 20 22 11 q5 2019-04-05 5 44 47 p6 2019-04-06 18 52 37 k7 2019-04-07 19 12 43 r8 2019-04-08 12 35 6 i9 2019-04-09 11 7 38 e10 2019-04-10 1 14 21 b11 2019-04-11 3 20 42 w12 2019-04-12 14 1 32 t13 2019-04-13 23 19 52 h14 2019-04-14 21 41 26 s15 2019-04-15 8 16 25 o> dataNew <- unite(data, datehour, date, hour, sep = ' ') # 联合date 和 hour两列,以空格分割,合成datehour列> dataNewdatehour min second event1 2019-04-01 7 30 29 u2 2019-04-02 9 43 36 a3 2019-04-03 13 58 60 l4 2019-04-04 20 22 11 q5 2019-04-05 5 44 47 p6 2019-04-06 18 52 37 k7 2019-04-07 19 12 43 r8 2019-04-08 12 35 6 i9 2019-04-09 11 7 38 e10 2019-04-10 1 14 21 b11 2019-04-11 3 20 42 w12 2019-04-12 14 1 32 t13 2019-04-13 23 19 52 h14 2019-04-14 21 41 26 s15 2019-04-15 8 16 25 o
separate—将一列分离为多列
separate(data, col, into, sep = “[[1]]+”, remove = TRUE, convert = FALSE, extra = “warn”, fill = “warn”, …) data:为数据框 col:需要被拆分的列 into:新建的列名,为字符串向量 sep:被拆分列的分隔符 remove:是否删除被分割的列
> data1 <- separate(dataNew, datehour, c('date', 'hour'), sep = ' ') # 江上编数据重新拆分成原样> data1date hour min second event1 2019-04-01 7 30 29 u2 2019-04-02 9 43 36 a3 2019-04-03 13 58 60 l4 2019-04-04 20 22 11 q5 2019-04-05 5 44 47 p6 2019-04-06 18 52 37 k7 2019-04-07 19 12 43 r8 2019-04-08 12 35 6 i9 2019-04-09 11 7 38 e10 2019-04-10 1 14 21 b11 2019-04-11 3 20 42 w12 2019-04-12 14 1 32 t13 2019-04-13 23 19 52 h14 2019-04-14 21 41 26 s15 2019-04-15 8 16 25 o
separate_rows可以间该数据分割后储存在同一列
> head(table3)# A tibble: 6 x 3country year rate<chr> <int> <chr>1 Afghanistan 1999 745/199870712 Afghanistan 2000 2666/205953603 Brazil 1999 37737/1720063624 Brazil 2000 80488/1745048985 China 1999 212258/12729152726 China 2000 213766/1280428583> separate_rows(table3, rate)# A tibble: 12 x 3country year rate<chr> <int> <chr>1 Afghanistan 1999 7452 Afghanistan 1999 199870713 Afghanistan 2000 26664 Afghanistan 2000 205953605 Brazil 1999 377376 Brazil 1999 1720063627 Brazil 2000 804888 Brazil 2000 1745048989 China 1999 21225810 China 1999 127291527211 China 2000 21376612 China 2000 1280428583
数据拓展
complete—创建组合table
complete和expand都会创建出一个包含所有组合的tibble,只是两者得到的结果是不一样的
> complete(mtcars, cyl, gear, carb)# A tibble: 74 x 12cyl gear carb car mpg disp hp drat wt qsec vs am<dbl> <dbl> <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>1 4 3 1 Toyota ~ 21.5 120. 97 3.7 2.46 20.0 1 02 4 3 2 NA NA NA NA NA NA NA NA NA3 4 3 3 NA NA NA NA NA NA NA NA NA4 4 3 4 NA NA NA NA NA NA NA NA NA5 4 3 6 NA NA NA NA NA NA NA NA NA6 4 3 8 NA NA NA NA NA NA NA NA NA7 4 4 1 Datsun ~ 22.8 108 93 3.85 2.32 18.6 1 18 4 4 1 Fiat 128 32.4 78.7 66 4.08 2.2 19.5 1 19 4 4 1 Toyota ~ 33.9 71.1 65 4.22 1.84 19.9 1 110 4 4 1 Fiat X1~ 27.3 79 66 4.08 1.94 18.9 1 1# ... with 64 more rows> expand(mtcars, cyl, gear, carb)# A tibble: 54 x 3cyl gear carb<dbl> <dbl> <dbl>1 4 3 12 4 3 23 4 3 34 4 3 45 4 3 66 4 3 87 4 4 18 4 4 29 4 4 310 4 4 4# ... with 44 more rows
缺失值处理
drop_na—去掉包含NA的某些行
> library(dplyr)> df <- tibble(x = c(1, 2, NA), y = c("a", NA, "b"))> df# A tibble: 3 x 2x y<dbl> <chr>1 1 a2 2 NA3 NA b> drop_na(df, x) # 去掉x列包含NA的行# A tibble: 2 x 2x y<dbl> <chr>1 1 a2 2 NA
fill—根据就近的非NA值补充NA数据
> df <- data.frame(x1 = LETTERS[1:5], x2 =c(1, NA, NA, 3, NA))> dfx1 x21 A 12 B NA3 C NA4 D 35 E NA> fill(df, x2)x1 x21 A 12 B 13 C 14 D 35 E 3> fill(df, x2, .direction = "up")x1 x21 A 12 B 33 C 34 D 35 E NA> fill(df, x2, .direction = "down")x1 x21 A 12 B 13 C 14 D 35 E 3
replace_na—取代缺失值
> replace_na(df, list(x2 = 2))x1 x21 A 12 B 23 C 24 D 35 E 2
- :alnum: ↩︎
