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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
禁止轉載,如需轉載請通過簡信或評論聯系作者。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內容