电竞比分网-中国电竞赛事及体育赛事平台

分享

R語言數(shù)據(jù)整理利器——dplyr

 醫(yī)學(xué)數(shù)據(jù)科學(xué) 2020-05-02

dplyr對于處理以行列關(guān)系表示的數(shù)據(jù)框(每一行是一個(gè)觀測值,每一列是一個(gè)維度)十分有效。首先dplyrSQL語句十分類似,其中select、filter、mutate、summarise等幾個(gè)關(guān)鍵的函數(shù),可以幫助我們非常方便的篩選、修改、匯總數(shù)據(jù)。此外dplyr還可以使我們非常便捷的對數(shù)據(jù)集進(jìn)行交并合補(bǔ)。最后dplyr中還引入了管道處理的概念(如x %>% f(y)等同于f(x, y)),使我們可以將運(yùn)算結(jié)果優(yōu)雅的傳遞給下一個(gè)函數(shù)處理,避免了嵌套運(yùn)用多個(gè)函數(shù)處理數(shù)據(jù)時(shí),必須使用多層括號或多個(gè)臨時(shí)變量的情形。

1、添加觀測值、添加變量

我們可以使用add_row、add_column函數(shù),添加觀測值、添加變量。類似于rbind、cbind函數(shù),但這兩個(gè)函數(shù)還可以在原數(shù)據(jù)框的任意位置插入行列。注意這兩個(gè)函數(shù)是根據(jù)tibble類型的數(shù)據(jù)框?qū)崿F(xiàn)的,不支持使用行名;此外add_row會對列名進(jìn)行更加嚴(yán)格的檢查,所以需要我們按照列名添加觀測值。

> df <- tibble(x = 1:3, y = 3:1)# 添加觀測值> add_row(df, x = 4, y = 0)# 添加變量> add_column(df, z = -1:1, w = 0)

2、修改行名、列名

我們可以使用rename函數(shù),重命名數(shù)據(jù)框中的某個(gè)變量。此外我們還可以使用rename_all、rename_at、rename_if函數(shù),對所有變量、對某些變量、對滿足特定條件的變量進(jìn)行重命名。

為了更好的在普通數(shù)據(jù)框與tibble類型的數(shù)據(jù)框之間轉(zhuǎn)換,我們可以將行名轉(zhuǎn)化為一個(gè)單獨(dú)的變量。使用rownames_to_column、column_to_rownames函數(shù),將行名轉(zhuǎn)化為變量、將變量轉(zhuǎn)化為行名。此外我們還可以使用has_rownames、remove_rownames函數(shù),判斷數(shù)據(jù)框是否有行名、刪除行名。

# 修改列名> rename(mtcars, var1 = "cyl", var2 ="am")# 將行名轉(zhuǎn)化為變量> rownames_to_column(mtcars)

3、篩選變量

我們可以使用select函數(shù),篩選變量、反選(刪除)變量、重命名變量、調(diào)整變量位置。此外我們還可以使用select_all、select_at、select_if函數(shù),對所有變量、對某些變量、對滿足特定條件的變量進(jìn)行篩選。注意篩選變量時(shí)我們既可以使用變量名,也可以使用字符串來篩選變量;反選變量時(shí)需要使用負(fù)號,此時(shí)相當(dāng)于篩選除了該變量之外的所有變量;我們可以在同一條命令中篩選多次,此時(shí)相當(dāng)于先按照篩選條件的先后順序進(jìn)行篩選,再取篩選結(jié)果的并集,即使某些變量多次被選擇,也只會在結(jié)果中出現(xiàn)一次。此外我們還可以在篩選語句中使用以下幫助函數(shù)以提高篩選效率。

函數(shù)解釋說明
starts_with、 ends_with篩選變量名以某個(gè)字符串開頭/結(jié)尾的變量(如select(mtcars, ends_with("t"))
contains篩選變量名中包含某個(gè)字符串的變量(如select(mtcars, contains("ar"))
matches篩選變量名中匹配某個(gè)正則表達(dá)式的變量(如select(mtcars, matches("\\w{4}"))
num_range篩選從某個(gè)變量到某個(gè)變量之間的所有變量(如select(mtcars, hp:am)
one_of篩選變量名在某個(gè)字符串?dāng)?shù)組中出現(xiàn)的變量(如select(mtcars, c("hp", "am"))
everything篩選所有變量(如select(mtcars, -hp, everything())
group_cols篩選分組變量(如mtcars %>% group_by(hp) %>% select(group_cols())
# 篩選變量> select(mtcars, hp : am)# 反選(刪除)變量> select(mtcars, -hp : -am)# 重命名變量> select(mtcars, var1 = "hp", var2 ="am")# 調(diào)整變量位置> select(mtcars, -hp, everything())

4、轉(zhuǎn)化變量

我們可以使用mutate函數(shù)轉(zhuǎn)化變量,并將新生成的變量添加到數(shù)據(jù)框中,或者直接用新生成的變量替換現(xiàn)有變量。但這種方式既會保留新生成的變量,也會保留原有的變量(除非我們使用NULL值來刪除某個(gè)變量)。如果我們只希望保留新生成的變量,則可以使用transmute函數(shù)。此外我們還可以使用mutate_all、mutate_at、mutate_if函數(shù),對所有變量、對某些變量、對滿足特定條件的變量進(jìn)行轉(zhuǎn)化。注意以上函數(shù)轉(zhuǎn)化變量時(shí),我們使用的函數(shù)需要返回與原始變量長度一致的變量,否則返回值會被重復(fù)使用。

# 轉(zhuǎn)化變量>  mutate(mtcars, wt = wt/mean(wt), am = NULL)# 對所有變量進(jìn)行轉(zhuǎn)化> mutate_all(mtcars, round, digits = 2)# 對某些變量進(jìn)行轉(zhuǎn)化> mutate_at(mtcars, vars(hp : am), round, digits = 2)# 對滿足特定條件的變量進(jìn)行轉(zhuǎn)化> mutate_if(mtcars, is.numeric, round, digits = 2)

4.1、變量轉(zhuǎn)化型函數(shù)

我們在使用mutate函數(shù)轉(zhuǎn)化變量時(shí),往往需要用到變量轉(zhuǎn)化型函數(shù)。這樣的函數(shù)往往需要接收一個(gè)(或多個(gè))變量作為參數(shù),并返回一個(gè)與其等長的新變量。這樣的函數(shù)可以是數(shù)學(xué)運(yùn)算函數(shù)(如+、-、log等)、邏輯運(yùn)算函數(shù)(如&、|、!等)、位運(yùn)算函數(shù)(如bitwAnd、bitwOr等)、字符串處理函數(shù)(如paste、sprintf等)。還可以是dplyr中提供的以下函數(shù):

函數(shù)解釋說明
lead求數(shù)組的n階前導(dǎo),如lead(co2, 12)
lag求數(shù)組的n階時(shí)滯
cumany以累計(jì)的形式求是否有真值
cumall以累計(jì)的形式求是否全為真值
cummean以累計(jì)的形式求平均值,其它 累計(jì)算法 還有cummax、cummin、cummean、cumsum
row_number數(shù)組按從小到大的順序排列之后對應(yīng)的行號,如mutate(mtcars, index = row_number())
ntile將數(shù)組從小到大分為n個(gè)等級,如ntile(euro, 5)
dense_rank數(shù)組中的值,對應(yīng)去重后從小到大排列的數(shù)組中的序號
min_rank數(shù)組按從小到大的順序排列之后對應(yīng)的序號(大小一致的值取最小行號)
percent_rank數(shù)組按從小到大的順序排列之后對應(yīng)的序號(大小一致的值取最小行號),再進(jìn)行比例化
cume_dist數(shù)組按從小到大的順序排列之后對應(yīng)的序號(大小一致的值取最大行號),再進(jìn)行比例化
between判斷數(shù)值是否在某個(gè)范圍內(nèi),如between(euro, 1, 10)
near判斷兩個(gè)數(shù)值是否在某個(gè)可接收范圍內(nèi)近似相等,如near(sqrt(2) ^ 2, 2)
if_else根據(jù)條件判斷式,決定處理數(shù)組取值的方式,如if_else(euro > 10, "10+", "10-")
case_when根據(jù)多個(gè)條件判斷式,處理數(shù)組中取值,如case_when(euro > 100 ~ "100+", euro > 10 ~ "10+", TRUE ~ "0+")
na_ifNA值替換數(shù)組中的某個(gè)值,如na_if(starwars$eye_color, "unknown")
coalesce以某個(gè)值替換數(shù)組中的NA值,如coalesce(c(1:10, NA), 0L)
recode以某個(gè)值替換數(shù)組中的特定值,如recode(1:10, "10" = 0L)
recode_factor以某個(gè)值替換因子型數(shù)組中的特定因子,如recode_factor(state.region, "Northeast" = "East")

5、排序觀測值

我們可以使用arrange函數(shù),將數(shù)據(jù)框中的觀測值按照某一個(gè)或多個(gè)變量的取值大小進(jìn)行排序。這些變量可以是連續(xù)變量,也可以是分類變量,如果變量是由字符構(gòu)成的,則會按照字符編碼進(jìn)行排序。使用多個(gè)變量排序時(shí),會先按照第一個(gè)變量的取值進(jìn)行排序,如果取值相同則再按照第二個(gè)變量進(jìn)行排序,依次類推,如果所有變量取值都一致,則保持觀測值的位置不變。排序時(shí)我們還可以使用desc函數(shù),獲取某個(gè)變量的逆序。

# 排序觀測值> arrange(mtcars, desc(carb), wt)

6、篩選觀測值

首先我們可以使用distinct函數(shù),根據(jù)某些變量,或全部變量篩選出不重復(fù)的觀測值。即使我們只根據(jù)部分變量進(jìn)行去重,也可以保留全部變量,此時(shí)保留的是第一條不重復(fù)的觀測值。

其次我們可以使用top_n、top_frac函數(shù),根據(jù)某個(gè)變量取值的大小,篩選出排在 前面 的一定數(shù)量或一定比例的觀測值。這里結(jié)合使用row_number、desc等函數(shù),即可像head、tail函數(shù)一樣,篩選出數(shù)據(jù)框的前n條、后n條值(或者按比例)。此外我們可以使用sample_n、sample_frac函數(shù),隨機(jī)篩選出一定數(shù)量或一定比例的觀測值。

再次我們還可以使用slice函數(shù),根據(jù)行號篩選、反選觀測值。注意此時(shí)我們可以使用n()來表示最大行號。

最后我們可以使用filter函數(shù),根據(jù)一個(gè)或多個(gè)邏輯數(shù)組(或生成邏輯數(shù)組的判斷函數(shù))篩選觀測值。此外我們還可以使用mutate_all、mutate_at、mutate_if函數(shù),對所有變量、對某些變量、對滿足特定條件的變量,按照特定的判斷函數(shù)進(jìn)行篩選。此時(shí)我們除了使用常規(guī)的比較運(yùn)算函數(shù)(如<、>、==等)、邏輯運(yùn)算函數(shù)(如&、|、!等)、數(shù)據(jù)類型判斷函數(shù)(如is.na等)之外,還可以使用between、near函數(shù),來判斷數(shù)值型變量的取值是否在某個(gè)范圍內(nèi)。

# 根據(jù)特定變量去重,保留第一條不重復(fù)的觀測值> distinct(mtcars, cyl, gear, .keep_all = TRUE)# 篩選前10%的觀測值> top_frac(mtcars, 0.1, desc(row_number()))# 隨機(jī)抽取50條觀測值(可重復(fù)抽取)> sample_n(mtcars, 50, replace = TRUE, weight = mpg)# 去除第5條至最后一條觀測值> slice(mtcars, -5:-n())# 篩選滿足特定條件的觀測值> filter(mtcars, hp > mean(hp), near(wt, 2.7, tol = .1))

7、匯總觀測值

我們可以使用tally、count函數(shù),查詢數(shù)據(jù)框中有多少條觀測值。二者的區(qū)別在于:tally常被用于計(jì)算數(shù)據(jù)框整體包含了多少條觀測值,而count則常被用于計(jì)算某個(gè)變量取特定值時(shí)對應(yīng)有多少條觀測值。

我們可以使用summarise函數(shù),對數(shù)據(jù)框進(jìn)行匯總。此外我們還可以使用summarise_if、summarise_at、summarise_all函數(shù),對所有變量、對某些變量、對滿足特定條件的變量進(jìn)行匯總。注意匯總時(shí)需要使用的函數(shù),往往只需要返回一個(gè)值作為匯總結(jié)果。

# 匯總觀測值數(shù)量> summarise(mtcars, n())# 匯總?cè)ブ睾蟮挠^測值數(shù)量> distinct(mtcars, wt) %>% tally()# 匯總某個(gè)變量取特定值時(shí)對應(yīng)有多少條觀測值> count(mtcars, cyl)

7.1、變量匯總型函數(shù)

我們在使用summarise函數(shù)匯總變量時(shí),往往需要用到變量匯總型函數(shù)。這樣的函數(shù)往往需要接收一個(gè)(或多個(gè))變量作為參數(shù),并返回一個(gè)單一的值作為匯總結(jié)果。這樣的函數(shù)可以是分位數(shù)計(jì)算函數(shù)(如median、min、max、quantile等)、特征值計(jì)算函數(shù)(如sum、mean、IQR、var、sd、mad等)、邏輯值匯總函數(shù)(如any、all等),還可以是dplyr中提供的以下函數(shù):

函數(shù)解釋說明
n查詢數(shù)組包含多個(gè)個(gè)值
n_distinct查詢數(shù)組包含多少個(gè)不同的值
first獲取數(shù)組的第一個(gè)值
last獲取數(shù)組的最后一個(gè)值
nth獲取數(shù)組的第n個(gè)值

8、分組

我們可以使用group_by函數(shù),將數(shù)據(jù)框按某些變臉進(jìn)行分組,對分組之后的數(shù)據(jù)框進(jìn)行的任何操作,都相當(dāng)于先在組內(nèi)進(jìn)行相應(yīng)的操作,然后再依次合并操作結(jié)果。如果需要取消分組,則可以使用ungroup函數(shù)。

# 分組轉(zhuǎn)化變量> mtcars %>% group_by(cyl) %>% mutate(wt = wt/mean(wt))# 分組篩選最后一條數(shù)據(jù)> mtcars %>% group_by(cyl) %>% top_n(1, row_number())# 分組匯總> mtcars %>% group_by(cyl) %>% count()

9、交并合補(bǔ)

我們可以使用bind_rows、bind_cols函數(shù),對兩個(gè)數(shù)據(jù)框進(jìn)行縱向、橫向合并。類似于rbind、cbind函數(shù),但這兩個(gè)函數(shù)會對行列進(jìn)行更加嚴(yán)格的檢查,所以使用bind_rows縱向合并時(shí),可以根據(jù)變量名合并數(shù)據(jù);而使用bind_cols橫向合并時(shí),需要兩個(gè)數(shù)據(jù)框擁有相同數(shù)量的觀測值。

> df <- tibble(x = 1:3, y = 3:1)
> df1 <- tibble(x = 4, y = 0)
> df2 <- tibble(z = -1:1, w = 0)# 縱向合并> bind_rows(df, df1)# 橫向合并> bind_cols(df, df2)

類似R語言系統(tǒng)函數(shù)中對數(shù)組進(jìn)行交并合補(bǔ),我們也可以使用union、intersect、setdiff函數(shù),取得兩個(gè)數(shù)據(jù)框的并集、交集、補(bǔ)集。并使用setequal函數(shù)判斷兩個(gè)數(shù)據(jù)框是否相同。此外,如果取并集時(shí)需要包含重復(fù)的觀測值,則可以使用union_all函數(shù)。

> df1 <- tibble(k = c("A", "B", "C"), v = 1:3)
> df2 <- tibble(k = c("B", "C", "D"), v = 2:4)# 取并集> union(df1, df2)# 取交集> intersect(df1, df2)# 取補(bǔ)集> setdiff(df1, df2)

10、數(shù)據(jù)框連接

我們可以使用left_join、right_join、inner_join、full_join函數(shù),將兩個(gè)數(shù)據(jù)框按照一個(gè)或多個(gè)變量,進(jìn)行左連接、右連接、內(nèi)連接、外連接。此時(shí)左右兩個(gè)數(shù)據(jù)框用于連接的變量名稱可以相同,也可以不同,我們可以使用by參數(shù)指定使用哪些同名變量進(jìn)行連接,或者左右兩個(gè)數(shù)據(jù)框的哪些變量應(yīng)當(dāng)一一對應(yīng);除此之外如果還包含其它同名變量,則連接后為了區(qū)分同名變量,默認(rèn)會給左邊數(shù)據(jù)框中的同名變量添加.x后綴,而給右邊的添加.y后綴,我們可以使用suffix參數(shù)修改這一設(shè)定。

此外我們還可以使用semi_join、anti_join函數(shù),進(jìn)行半連接、反連接。這兩種方式分別與取差集、補(bǔ)集的形式十分類似,但可以通過數(shù)據(jù)框中的部分變量來決定差集、補(bǔ)集。

> df1 <- tibble(k = c("A", "B", "C"), v = 1:3)
> df2 <- tibble(k = c("B", "C", "D"), v = 3:1, u = c("A", "B", "D"))# 左連接,左右數(shù)據(jù)框用于連接的變量名稱相同> df1 %>% left_join(df2, by = "k")# 右連接,左右數(shù)據(jù)框用于連接的變量名稱不相同> df1 %>% right_join(df2, by = c("k" = "u"))# 內(nèi)連接,使用默認(rèn)后綴處理同名變量> inner_join(df1, df2, by = "k")# 外連接,使用自定義后綴處理同名變量> full_join(df1, df2, by = "k", suffix = c("1",  "2"))# 半連接,類似于取差集> df1 %>% semi_join(df2, by = "k")# 反連接,類似于取補(bǔ)集> df1 %>% anti_join(df2, by = "k")

上方的的速記手冊,可以幫助我們快速了解dplyr的整體框架與各項(xiàng)細(xì)節(jié)。獲取更多速記手冊,請前往 這里 。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多