R語言基礎5--tidyr包的函數及用法


R語言基礎系列:


tidyr包的應用
  • tidyr主要提供了一個類似Excel中數據透視表(pivot table)的功能。
  • gather()spread()函數將數據在長格式和寬格式之間相互轉化,應用在比如稀疏矩陣和稠密矩陣之間的轉化。(用于數據框 )
  • separate()union()方法提供了數據分組拆分、合并的功能,應用在nominal數據的轉化上。(用于數據框 )
  • tidyr還提供一些簡單的缺失值處理方法。
# 查看這個包的網頁說明書
browseVignettes('tidyr')
1. gather實現wide 到 long 轉換

類似reshape2包中melt函數的功能

  • 語法
gather(data, key = "key", value = "value",..., na.rm = FALSE, convert = FALSE, factor_key = FALSE)
  • 參數
參數 含義
data 需要被轉換的寬形數據框
key 將原數據框中的所有列賦給一個新變量key
value 將原數據框中的所有值賦給一個新變量value
可以指定哪些列聚到同一列中,可用于選擇兩列之間的所有列col1:coln, 排除列-coln
na.rm 是否刪除缺失值,默認為FALSE
convert 為TRUE時會自動在key列上使用type.convert函數,默認值為FALSE
factor_key FALSE時key值為字符向量,TRUE時key值為factor類型
  • 使用
library(tidyr)
library(dplyr)
stocks <- tibble(
  time = as.Date('2009-01-01') + 0:9,
  X = rnorm(10, 0, 1),
  Y = rnorm(10, 0, 2),
  Z = rnorm(10, 0, 4)
)
stocks
#  A tibble: 10 x 4
#    time             X      Y      Z
#    <date>       <dbl>  <dbl>  <dbl>
 # 1 2009-01-01 -0.326   3.32   5.84 
#  2 2009-01-02  0.410   3.99  -1.97 
#  3 2009-01-03 -0.344  -0.394  4.09 
#  4 2009-01-04 -1.11    1.12  -5.43 
#  5 2009-01-05 -0.374   0.303  0.336
#  6 2009-01-06  2.72    1.38  -4.86 
#  7 2009-01-07  0.416   3.39  -1.27 
#  8 2009-01-08  2.31    1.25  -2.13 
#  9 2009-01-09 -0.0643  4.87   1.37 
# 10 2009-01-10 -0.0232  2.73   1.38 

gather(stocks, "stock", "price", -time)
stocks %>% gather("stock", "price", -time)
#  A tibble: 30 x 3
#    time       stock   price
#    <date>     <chr>   <dbl>
#  1 2009-01-01 X     -0.326 
#  2 2009-01-02 X      0.410 
#  3 2009-01-03 X     -0.344 
#  4 2009-01-04 X     -1.11  
#  5 2009-01-05 X     -0.374 
#  6 2009-01-06 X      2.72  
#  7 2009-01-07 X      0.416 
#  8 2009-01-08 X      2.31  
#  9 2009-01-09 X     -0.0643
# 10 2009-01-10 X     -0.0232
#  … with 20 more rows
2. spread實現long 到wide轉換(類似reshape2包中cast函數的功能)
  • 語法
spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE, sep = NULL)
  • 參數
參數 含義
data 為需要轉換的長形data.frame
key 設置需要擴寬的類別變量
value 設置需要擴寬的變量的度量值
fill 對于缺失值,可將fill的值賦值給被轉型后的缺失值
convert 為TRUE時會自動在新列上使用type.convert函數,其中as.is = TRUE,默認值為FALSE
drop 為FALSE保留factor的level,使用fill的值填充missing的值
sep 為默認值NULL時,新列名使用key中的值,非NULL時,新列名為<key_name><sep><key_value>
  • 使用
library(dplyr)
stocks <- data.frame(
  time = as.Date('2009-01-01') + 0:9,
  X = rnorm(10, 0, 1),
  Y = rnorm(10, 0, 2),
  Z = rnorm(10, 0, 4)
)
stocks
#  A tibble: 10 x 4
#    time             X      Y      Z
#    <date>       <dbl>  <dbl>  <dbl>
 # 1 2009-01-01 -0.326   3.32   5.84 
#  2 2009-01-02  0.410   3.99  -1.97 
#  3 2009-01-03 -0.344  -0.394  4.09 
#  4 2009-01-04 -1.11    1.12  -5.43 
#  5 2009-01-05 -0.374   0.303  0.336
#  6 2009-01-06  2.72    1.38  -4.86 
#  7 2009-01-07  0.416   3.39  -1.27 
#  8 2009-01-08  2.31    1.25  -2.13 
#  9 2009-01-09 -0.0643  4.87   1.37 
# 10 2009-01-10 -0.0232  2.73   1.38 

stocksm <- stocks %>% gather(stock, price, -time)
head(stocksm)
#         time stock      price
# 1 2009-01-01     X  0.8126651
# 2 2009-01-02     X -0.3387208
# 3 2009-01-03     X -0.6778238
# 4 2009-01-04     X  0.3713640
# 5 2009-01-05     X -1.5019406
# 6 2009-01-06     X -0.8858434

stocksm %>% spread(stock, price)
#          time           X           Y           Z
# 1  2009-01-01  0.81266513 -2.21316283   7.9265756
# 2  2009-01-02 -0.33872080  3.52921094  -1.2218472
# 3  2009-01-03 -0.67782385 -1.82005963   1.2567876
# 4  2009-01-04  0.37136402 -1.22181178  -0.2963697
# 5  2009-01-05 -1.50194061 -1.56952607   3.1274926
# 6  2009-01-06 -0.88584341  5.17005476 -10.9974695
# 7  2009-01-07  0.22308469  0.07021010  -3.2228298
# 8  2009-01-08  0.08303945 -5.20103460  -0.1731917
# 9  2009-01-09 -0.58188891 -0.47327216   0.7320103
# 10 2009-01-10 -0.33931690  0.01911578  -7.2114319
stocksm %>% spread(time, price)
#   stock 2009-01-01 2009-01-02 2009-01-03 2009-01-04 2009-01-05  2009-01-06
# 1     X  0.8126651 -0.3387208 -0.6778238  0.3713640  -1.501941  -0.8858434
# 2     Y -2.2131628  3.5292109 -1.8200596 -1.2218118  -1.569526   5.1700548
# 3     Z  7.9265756 -1.2218472  1.2567876 -0.2963697   3.127493 -10.9974695
#   2009-01-07  2009-01-08 2009-01-09  2009-01-10
# 1  0.2230847  0.08303945 -0.5818889 -0.33931690
# 2  0.0702101 -5.20103460 -0.4732722  0.01911578
# 3 -3.2228298 -0.17319172  0.7320103 -7.21143190
3. unite 可將多列按指定分隔符合并為一列
  • 語法
unite(data, col, ..., sep = "_", remove = TRUE)
  • 參數
參數 含義
data 為數據框
col 被組合的新列名稱
指定哪些列需要被組合, 可用于選擇兩列之間的所有列col1:coln, 排除列-coln
sep 組合列之間的連接符,默認為下劃線
remove 是否刪除被組合的列
  • 使用
df <- expand_grid(x = c("a", NA), y = c("b", NA))
df
#   A tibble: 4 x 2
#   x     y    
#   <chr> <chr>
# 1 a     b    
# 2 a     NA   
# 3 NA    b    
# 4 NA    NA 

df %>% unite("z", x:y, remove = FALSE) #若remove = TRUE,則不保留x和y列
#   A tibble: 4 x 3
#   z     x     y    
#  <chr> <chr> <chr>
# 1 a_b   a     b    
# 2 a_NA  a     NA   
# 3 NA_b  NA    b    
# 4 NA_NA NA    NA 

df %>% unite("z", x:y, na.rm = TRUE, remove = FALSE)
#   A tibble: 4 x 3
#   z     x     y    
#   <chr> <chr> <chr>
# 1 "a_b" a     b    
# 2 "a"   a     NA   
# 3 "b"   NA    b    
# 4 ""    NA    NA 
4. separate分割一列為多列

類似于reshape2中的colsplit函數

  • 語法
separate(data, col, into, sep = "[^[:alnum:]]+", remove = TRUE, convert = FALSE, extra = "warn", fill = "warn", ...)
  • 參數
參數 含義
data 為數據框
col 需要被拆分的列
into 新建的列名,為字符串向量
sep 被拆分列的分隔符
remove 是否刪除被分割的列
convert 為TRUE時會自動在新列上使用type.convert函數,其中as.is = TRUE,默認值為FALSE
extra 當分割成的列多于length(into)時,"warn"(默認值) 發出警告并刪除多余值,"drop"直接刪除多余值,"merge"僅分割length(into)次
fill 當分割成的列少于length(into)時,"warn"(默認值) 發出警告并從右側填充缺失值,"right"直接從右側填充缺失值,"left"直接從左側填充缺失值
  • 使用
library(dplyr)
df <- data.frame(x = c(NA, "a.b", "a.d", "b.c"))
#分割為兩列,保留NA值
df %>% separate(x, c("A", "B"))
df <- data.frame(x = c("a", "a b", "a b c", NA))
#分割為兩列,發出warning并刪除多余的列,缺失的列從右以NA填充
df %>% separate(x, c("a", "b"))
#分割為兩列,直接刪除多余的列,缺失的列從右以NA填充
df %>% separate(x, c("a", "b"), extra = "drop", fill = "right")
#分割兩次(設置的列為兩列),缺失的列從左以NA填充
df %>% separate(x, c("a", "b"), extra = "merge", fill = "left")
df <- data.frame(date = c("2017-03-08 01:20:20", "2017-03-09 02:30:30", "2017-03-10 03:40:40"))
#分割為year,month,day,hour,minute,second六列
df %>% 
  separate(date, c("day", "time"), sep = " ") %>%
  separate(day, c("year", "month", "day"), sep = "-") %>% 
  separate(time, c("hour", "minute", "second"), sep = ":") 

與separate不同的是extract使用正則表達式regex提取需要分割的列,當輸入為NA或者不能匹配regex時,輸出為NA。

extract(data, col, into, regex = "([[:alnum:]]+)", remove = TRUE, convert = FALSE, ...)
library(dplyr)
df <- data.frame(x = c(NA, "a.b", "a.d", "b.c"))
#分割為兩列,regex匹配要分割的列
df %>% extract(x, c("a", "b"), regex = "([a-d]+).([a-d]+)")
df %>% extract(x, c("A", "B"), "([[:alnum:]]+).([[:alnum:]]+)")
#分割為兩列,regex匹配要分割的列,不能匹配列的輸出為NA
df %>% extract(x, c("a", "b"), regex = "([a-d]+).([a-c]+)")
#分割為一列
df %>% extract(x, c("a"), regex = "([a-d]+)")
df %>% extract(x, c("a"))

separate_rows用于將列分割為多行,”... ”用于設置需要分割的列,sep用于設置分隔符,需要注意的是分割多個列時,每個列分割成的行數必須要一致。

separate_rows(data, ..., sep = "[^[:alnum:].]+", convert = FALSE)
library(dplyr)
df <- data.frame(
  x = 1:3,
  y = c("a", "d,e,f", "g,h"),
  z = c("1", "2,3,4", "5,6"),
  stringsAsFactors = FALSE
)
#分割y和z列,轉換為行
separate_rows(df, y, z, convert = TRUE)
5. 缺失值處理

tidyr包提供了簡單的缺失值處理方法,包括替換,填充,刪除等

  • 使用給定值替換每列的缺失值
replace_na(data, replace = list(), ...)
# data:為數據框
# replace:替換值用于替換每個列中NA
library(dplyr)
df <- tibble(x = c(1, 2, NA), y = c("a", NA, "b"))
#以0替換x中的NA,以unknown替換y中的NA
df %>% replace_na(list(x = 0, y = "unknown"))
  • 以前一個值填充缺失值,默認自上向下填充
fill(data, ..., .direction = c("down", "up"))
# data:為數據框
# …:指定需要被填充的列, 可用于選擇兩列之間的所有列col1:coln, 排除列-coln
# .direction :填充的方向,默認為down,自上向下填充
df <- data.frame(x = 1:5, y = c(10, NA, 15, NA, 20))
#自上向下替換NA值
df %>% fill(y)
df %>% fill(y, .direction = "down")
#自下向上替換NA值
df %>% fill(y, .direction = "up")
  • 填充以創建完整的序列值向量
full_seq(x, period, tol = 1e-06)
# x:數值向量
# period:觀測值間的間隔,并檢測現有數據是否與這個間隔匹配,,不匹配時報錯
#返回序列1:6
full_seq(c(1, 2, 4, 6), 1)
#period值與原數據間隔不匹配,報錯Error: `x` is not a regular sequence.
full_seq(c(1, 2, 4, 6), 2)
#返回序列1:13,間隔為2
full_seq(c(1, 5, 9, 13), 2)
  • 刪除包含缺失值的行
drop_na(data, ...)
# data:為數據框
# …:指定需要被填充的列, 可用于選擇兩列之間的所有列col1:coln, 排除列-coln
df <- data_frame(x = c(1, 2, NA), y = c("a", NA, "b"))
#刪除變量x中NA對應的行
df %>% drop_na(x)
#刪除變量y中NA對應的行
df %>% drop_na(y)
#未設置列,刪除變量x和y中NA對應的行
df %>% drop_na()
  • 轉換隱式的缺失值為顯式的
complete(data, ..., fill = list())
# data:為數據框
# …:指定需要擴展的列,每個輸入列都作為一個獨立的參數用于擴展數據框。其中使用crossing或者直接輸入列作為參數時,會使用每個列中的元素進行擴展,即使生成的組合在原數據框中不存在;而使用nesting函數時,返回的每個列元素的組合必須在原數據框中存在。
# fill:用于設置填充值以替換NA
df <- data_frame(
  group = c(1:2, 1),
  item_id = c(1:2, 2),
  item_name = c("a", "b", "b"),
  value1 = 1:3,
  value2 = 4:6
)
#以item_id和item_name中的每個元素擴展原數據框, 組合后的缺失值以NA代替
df %>% complete(item_id, item_name)
df %>% complete(crossing(item_id, item_name))
#以item_id和item_name中的每個元素擴展原數據框, 并以給定值替換缺失值
df %>% complete(item_id, item_name, fill = list(group = 0, value1 = 0, value2 = 0))
#以item_id和item_name中的每個元素擴展原數據框,只返回原數據框中存在的組合
df %>% complete(nesting(item_id, item_name))
 
#保留group,以item_id和item_name中的每個元素擴展原數據框,只返回原數據框
#中item_id和item_name存在的組合
df %>% complete(group, nesting(item_id, item_name))
df %>% complete(group, nesting(item_id, item_name), fill = list(value1 = 0, value2 = 0))
 
#保留group,以item_id和item_name中的每個元素擴展原數據框,返回所有item_id
#和item_name存在的組合
df %>% complete(group, crossing(item_id, item_name))
df %>% complete(group, crossing(item_id, item_name), fill = list(value1 = 0, value2 = 0))

參考:https://blog.csdn.net/wltom1985/article/details/107902563

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
禁止轉載,如需轉載請通過簡信或評論聯系作者。

推薦閱讀更多精彩內容