1. tibble數(shù)據(jù)
1.1 tibble數(shù)據(jù)簡介
“Tibbles are data frames, but they tweak some older behaviors to make life a little easier.”
——Hadley Wickham《R for data science》
Tibble是數(shù)據(jù)框的一種形式尔苦,但是比數(shù)據(jù)框更整潔翎卓,結(jié)構(gòu)更加緊湊楔绞,可以理解為tidy table之意
- 如果加載了tidyverse拉宗,統(tǒng)一采用tibble格式的數(shù)據(jù)集
1.2 tibble數(shù)據(jù)創(chuàng)建
可以通過tibble()
函數(shù)來像data.frame()
一樣來創(chuàng)建tibble數(shù)據(jù)
tibble(
x = 1:5,
y = 1,
z = x ^ 2 + y
)
或者可以通過轉(zhuǎn)置函數(shù)as_tibble()
來將data.frame格式的數(shù)據(jù)轉(zhuǎn)化為tibble格式的數(shù)據(jù)
as_tibble(mtcars)
- 需要注意的是蓖乘,不同于傳統(tǒng)的R語言
as.*
一類函數(shù)的用法故觅,對于變量類型的轉(zhuǎn)換酝惧,使用的是parse_*
函數(shù)族瞎饲,而對于數(shù)據(jù)集則使用的是as_*
函數(shù)族 - 并且轉(zhuǎn)化時沈善,tibble數(shù)據(jù)不會改變原始數(shù)據(jù)的任何信息
如果是想以表格的形式輸入數(shù)據(jù)乡数,可以使用tribble()
函數(shù)來創(chuàng)建,只是與tibble()
格式有點(diǎn)小小的不同:
tribble(
~x, ~y, ~z,
#--/--/----
'a', 2, 3.6,
'b', 3, 2.5
)
- 這種格式變量通常以「~」開頭
- 使用注釋符號來分隔符會使得輸入能整潔且便于對應(yīng)表頭
- 注意不要漏掉「,」半角逗號
1.3 tibble數(shù)據(jù)與傳統(tǒng)data.frame
tibble數(shù)據(jù)與data.frame數(shù)據(jù)相比主要在以下兩個方面有所不同:
- 打印輸出
- 子集索引
打印輸出
tibble數(shù)據(jù)輸出到console上只會顯示前10行闻牡,和所有列净赴;這對于大數(shù)據(jù)量而言是十分有益的
- 如果想獲取更詳細(xì)的信息,使用
str()
函數(shù)來提取
如果想明確輸出具體的打印信息罩润,可以在print()
函數(shù)中設(shè)置n=#
和width=Inf
玖翅,分別對應(yīng)行和列的數(shù)量饭入;
當(dāng)然還可以設(shè)定默認(rèn)打印輸出的參數(shù),主要有以下三個選項(xiàng)可供修改:
# 最大最小打印值
options(tibble.print_max = m,
tibble.print_min = n)
# 輸出所有行
options(dplyr.print_min = Inf)
# 輸出所有列
options(tibble.width = Inf)
- 如果想獲取更多可以使用
package?tibble
查看
子集索引
tibble索引與傳統(tǒng)data.frame格式索引一致迁沫,主要差別在:
tibble數(shù)據(jù)使用的是嚴(yán)謹(jǐn)?shù)娜科ヅ湮绻噲D索引一個不存在的列,其會生成警告
小結(jié)
- tibble是data.frame的一種审姓,但結(jié)構(gòu)更緊湊珍特、簡潔
- 創(chuàng)建tibble數(shù)據(jù)有
tibble()
和tribble()
兩個函數(shù),也可以通過as_tibble()
來轉(zhuǎn)換 - tibble與data.frame的區(qū)別在于輸出打印和子集索引上魔吐,并且R許多基礎(chǔ)的函數(shù)功能可能對與tibble數(shù)據(jù)并不起作用扎筒,因此如果需要用到某些函數(shù)功能時,可能需要將tibble數(shù)據(jù)轉(zhuǎn)換成data.frame格式
2. 數(shù)據(jù)整理之tidyr包應(yīng)用
2.1 什么是tidy數(shù)據(jù)
tidy數(shù)據(jù)表示的是已經(jīng)整理好的酬姆、整潔的數(shù)據(jù)嗜桌,通常現(xiàn)實(shí)中的數(shù)據(jù)許多都是混亂辞色,甚至是「臟」的骨宠,將這些數(shù)據(jù)進(jìn)行處理后所得到的數(shù)據(jù)就可以稱之為tidy數(shù)據(jù)
tidyverse包中的其他包都是為tidy數(shù)據(jù)而設(shè)計(jì)的;也可以說相满,tibble格式的數(shù)據(jù)就是tidy數(shù)據(jù)的表現(xiàn)形式层亿;通識tidy數(shù)據(jù)有以下三個方面的特征:
- 每個變量都對應(yīng)著單獨(dú)的一列
- 每條記錄都對應(yīng)著單獨(dú)的一行
- 每個觀察值都對應(yīng)著單獨(dú)的單元格
2.2 數(shù)據(jù)預(yù)處理函數(shù)
2.2.1 分散與聚合
在現(xiàn)實(shí)的分析中,往往需要對數(shù)據(jù)進(jìn)行的初步處理立美,使數(shù)據(jù)變得整潔:
- 第一步是需要確定變量和觀察值是哪些
- 使確定好的變量和觀察值能夠分別很好地對應(yīng)列和行
spread函數(shù)
分散函數(shù)是將變量中的值拆分成新的變量匿又,這個過程概括為就是將為成「列」的值,進(jìn)行拆分建蹄,并指定其他列作為「值」碌更,組合成「鍵-值」對的形式
#spread函數(shù)語法
spread(data, key= , value=, )
#以table2數(shù)據(jù)集為例子
table2 #查看數(shù)據(jù)集
table2 %>%
spread(key = 'type', value = 'count')
將type
列的值拆分作為「鍵」,count
列的值則作為每個鍵下的「值」洞慎,進(jìn)而將變量值進(jìn)行拆分
gather函數(shù)
在一些數(shù)據(jù)中存在的問題是痛单,列名并非是變量名,反而是變量的某個具體值劲腿,因此就需要將這些已經(jīng)成為列的「值」聚合到一起桦他,還原成其本來歸屬的變量里;聚合函數(shù)與分散函數(shù)是一對互逆的過程
#gather函數(shù)語法
gather(data, set_colums, key= , value=, ...)
# 以tidyverse包中的table4a數(shù)據(jù)為例
table4a #查看數(shù)據(jù)集
table4a %>%
gather(`1999`, `2000`,
key = 'year', value = 'cases')
簡而言之谆棱,gather函數(shù)就是將成為列的「值」進(jìn)行「鍵-值」形式的拆分:
- 每個
1999
和2000
都對應(yīng)著一個不同的值快压; - 因此根據(jù)
gather
函數(shù)中的key
和value
參數(shù)不難發(fā)現(xiàn),前者是為1999
和2000
指定新的「鍵」垃瞧,即變量蔫劣;而后者則為這些「值」指定新的變量
通過觀察可以很容易看出:
-
gather()
函數(shù)是將數(shù)據(jù)寬格式數(shù)據(jù)轉(zhuǎn)化為長且窄的格式數(shù)據(jù),這對于ggplot2包的使用極其有用 - 而
spread()
函數(shù)則是將長格式數(shù)據(jù)轉(zhuǎn)化為短且寬格式數(shù)據(jù)
2.2.2 拆分與黏合
分散與聚合是處理將變量與值進(jìn)行轉(zhuǎn)化時使用到的函數(shù)个从;而有時需要將一個列中的值拆分成兩個變量的值脉幢,或者將兩個變量的值組合成一個新的變量的值歪沃,這時候就需要使用到拆分與黏合函數(shù)
separate函數(shù)
#separate函數(shù)語法
separate(data, col, into= )
#以table3數(shù)據(jù)集為例子
table3 #查看數(shù)據(jù)集
table3 %>%
separate(rate, into=c('cases','population'))
- 從語法和例子上可以清楚的了解到
separate
參數(shù)的指定過程 - 但是該函數(shù)默認(rèn)是將非字母和數(shù)字的字符進(jìn)行分隔,如果希望指定分隔符嫌松,則需要額外使用
sep= ''
參數(shù)-
如果是要將數(shù)字進(jìn)行分隔沪曙,那么使用
sep
參數(shù)時需要注意位數(shù)的正負(fù):-
sep=1
時,則是從左往右進(jìn)行位數(shù)拆分 -
sep=-1
時萎羔,則是從右往左進(jìn)行位數(shù)拆分
-
-
- 并且要注意拆分后變量的類型液走,有可能會并非正確的數(shù)據(jù)類型,因此需要在轉(zhuǎn)換時加上
convert =T
參數(shù)來確保變量轉(zhuǎn)換成正確的類型
unite函數(shù)
同分散與聚合一樣贾陷,拆分與黏合函數(shù)同樣時一對互逆的函數(shù)與過程缘眶;黏合函數(shù)是將兩列變量的值黏合到一起,組成新的變量
#unite函數(shù)語法
unite(data, new_col, old_cols)
#接著separate的例子
table3 %>%
separate(year, into=c('century','year')) %>%
unite(new_year, century, year)
-
unite()
函數(shù)默認(rèn)使用「_」來聯(lián)結(jié)黏合的值髓废,可以通過sep
參數(shù)來調(diào)整 - 拆分與黏合的語法基本一致巷懈,不同的是在第二個參數(shù)的使用上
2.2.3 缺失值處理
缺失值的存在方式主要可能有兩種:
- 直接用NA來表明
- 間接的使用其他方式來呈現(xiàn):如應(yīng)該出現(xiàn)的卻沒有出現(xiàn)、NULL慌洪、stata中的「.」等顶燕,這些都有可能是缺失值
complete
complete()
函數(shù)是將數(shù)據(jù)集中所有不重復(fù)的列組合到一起進(jìn)行展示,對于原始數(shù)據(jù)缺失的值用NA來進(jìn)行填充
#complete函數(shù)語法
complete(data, unique_cols,...)
fill
fill()
函數(shù)通過名稱可以很容易得知冈爹,這是將缺失值進(jìn)行替換的函數(shù):
#設(shè)定數(shù)據(jù)集
treatment <- tribble(
~ person, ~ treatment, ~response,
#-----------------/------------/----------/
"Derrick Whitmore", 1, 7,
NA, 2, 10,
NA, 3, 9,
"Katherine Burke", 1, 4
)
treatment %>%
fill(person)
fill()
函數(shù)默認(rèn)是用NA值的前面一個值來覆蓋NA涌攻,如果想調(diào)整方向,可以使用.direction=c('up')
參數(shù)來進(jìn)行調(diào)整
- 如果忘記參數(shù)可以使用
?fill
查看幫助文檔
小結(jié)
- 本小節(jié)主要設(shè)計(jì)三組對于數(shù)據(jù)預(yù)處理的函數(shù):分散與聚合犯助、拆分與黏合、缺失值展示與填充
- 分散與聚合是將以「鍵-值」對的形式來展開轉(zhuǎn)化
- 拆分與黏合是將單個值或多個變量拆分或黏合成一個或多個變量的過程
- 缺失值的存在方式有直接和間接兩種
運(yùn)用案例
使用「who」數(shù)據(jù)集维咸,對數(shù)據(jù)集進(jìn)行整理并最后得到tidy數(shù)據(jù)
library(tidyverse)
who
查看數(shù)據(jù)集剂买,可以發(fā)現(xiàn):
- iso2和iso3表示地名
- year為變量,不需要變動
- 其他一系列的函數(shù)同名較多癌蓖,可能為值瞬哼,需要進(jìn)行聚合
who %>%
gather(new_sp_m014:newrel_f65,
key = "key", value = "cases", na.rm = TRUE)
對數(shù)據(jù)列進(jìn)行聚合,并且刪除缺失值
之后通過查看key
變量的頻數(shù)可以發(fā)現(xiàn)每個取值都是有規(guī)律的租副,都是由「_」下劃線來分隔坐慰,因此只需要以「_」來分隔來決定是否對分隔后的變量保留即可;
但是有一點(diǎn)需要注意的是用僧,newrel
的一系列值并沒有下劃線结胀,因此需要額外使用到stringr包中的str_replace來對這一系列值進(jìn)行分隔符添加,然后再進(jìn)行分隔
#str_replace函數(shù)語法
library(stringr)
str_replace(string, pattern, replacement)
#添加下劃線
who %>%
mutate(key = stringr::str_replace(key, 'newrel', 'new_rel') %>%
separate(key, c('new', 'type', 'sexage'), sep = '_')
最后需要再對sexage
進(jìn)行拆分责循,然后刪除冗余的變量糟港,保留需要的變量即可
who %>%
select(-iso2, -iso3, -new) %>%
separate(sexage, c('sex', 'age'), sep = 1))
- 注意
sep=1
是指定從左往右分隔1位數(shù)
完整代碼:
who %>%
gather(new_sp_m014:newrel_f65,
key = 'key', value = 'cases', na.rm = T) %>%
mutate(key = stringr::str_replace(key, 'newrel', 'new_rel')) %>%
separate(key, c('new', 'type', 'sexage'), sep = '_') %>%
select(-iso2, -iso3, -new) %>%
separate(sexage, c('sex', 'age'), sep = 1)
- 使用到的stringr包的
str_replace()
函數(shù)以及select()
和mutate()
函數(shù)為后面章節(jié)的函數(shù)