數(shù)據(jù)清洗之dplyr

本文來源于陳興棟、張鐵軍、劉振球老師編寫的《R語言與數(shù)據(jù)清洗》第九章數(shù)據(jù)匯總操作的學(xué)習(xí)筆記。dplyr包由Hadley Wickham創(chuàng)建,dplyr提供靈活的數(shù)據(jù)操作語法,專注于處理數(shù)據(jù)框的工具。要了解有關(guān)dplyr的更多信息,請從vignettes開始:

browseVignettes(package =“dplyr”)

dplyr包主要功能:

  1. 篩選各種變量select()
  2. 根據(jù)一個或者多個變量進行排序arrange()
  3. 變量重命名以及增加新的變量names()或者colnames()&mutate()
  4. 根據(jù)某個變量進行分類匯總summarize()
  5. 簡單隨機抽樣sample()
  6. 各種連接inner_join()等
  7. 按行或者按列進行合并rbind()或者cbind()

1. tbl_df函數(shù)

過長過大的數(shù)據(jù)集顯示為友好的表模式展現(xiàn)。

首先要安裝并載入這個dplyr包
library(dplyr) 
#查看mtcars的數(shù)據(jù)類型 
class(mtcars)
mtcars_df<- tbl_df(mtcars)

2.filter函數(shù)

與subset類似,按照邏輯條件篩選子集,支持任意條件組合,用“&”連接。

#查看數(shù)據(jù)集mtcars_df的結(jié)構(gòu)(有哪些變量,每個變量的類型等等)
str(mtcars_df) 

unique(mtcars_df$gear)

#過濾出gear == 4的行
filter(mtcars_df, gear == 4)

#過濾出drat<3的行
filter(mtcars_df, drat<3)

#過濾出cyl < 6 并且 gear == 4的行
filter(mtcars_df, cyl < 6 & gear == 4)

#如下命令也能得到相同的結(jié)果
filter(mtcars_df, cyl < 6, gear == 4)

#過濾出cyl== 6或者carb > 5的行
filter(mtcars_df, cyl== 6 |carb > 5)

#過濾出carb為2或4的行
filter(mtcars_df, carb %in% c(2, 4))

#過濾出carb為2或4的行
filter(mtcars_df, carb %in% c(2, 4))

#選取第3行數(shù)據(jù)。注意3L是長型數(shù)值的寫法。
slice(mtcars_df, 3L)

#或者使用filter函數(shù),也能達到同樣的目的:
filter(mtcars_df, row_number() == 3L)

#選取第3行數(shù)據(jù)。注意3L是長型數(shù)值的寫法。
slice(mtcars_df, 3L)

#或者使用filter函數(shù),也能達到同樣的目的:
filter(mtcars_df, row_number() == 3L)

3. slice函數(shù)

用于選出特定的幾行數(shù)據(jù),類似于“數(shù)據(jù)切片”

#選取最后一行數(shù)據(jù)
slice(mtcars_df, n())

#選取第1行到第10行所有的數(shù)據(jù),也可以使用slice函數(shù)或者filter函數(shù):
slice(mtcars_df, 1:10)
filter(mtcars_df, between(row_number(), 1,10))

4. arrange函數(shù)

按照給定的列,對行進行排序。默認升序,對列名加desc()函數(shù)可以實現(xiàn)降序排序。原數(shù)據(jù)集行名稱會被過濾掉。

#以變量qsec按升序排序(從小到大排序)
arrange(mtcars_df,qsec)

#以變量qsec按降序(從大到?。┡判?arrange(mtcars_df, desc(qsec))

#以qsec和disp聯(lián)合升序排序。也就是說:首先按照qsec的升序(從小到大)排序;如果在qsec相等的情形下,則按照disp從小到大排序。
arrange(mtcars_df, qsec, disp)

#首先按照qsec的升序(從小到大)排序;如果在qsec相等的情形下,則按照disp的降序(從大到?。┡判?。
arrange(mtcars_df, qsec, desc(disp))

5. select()函數(shù)

根據(jù)傳入的列名選擇子數(shù)據(jù)集。

#選出mtcars這個數(shù)據(jù)集的cyl,gear,carb 這三列數(shù)據(jù)
select(mtcars_df,cyl,gear,carb)

#“:”使用冒號連接列名,選擇多個列。例如選出mtcars這個數(shù)據(jù)集中從 hp這一列到 vs這一列之間的所有列數(shù)據(jù)
select(mtcars_df,hp:vs)

# “-” 用來刪除不要的列數(shù)據(jù)。例如,刪除數(shù)據(jù)集中從 hp這一列到 vs這一列之間的所有列數(shù)據(jù),返回剩余的數(shù)據(jù)集。
select(mtcars_df,-(hp:vs))

iris_df <- tbl_df(iris)
str(iris_df)

#選取變量名前綴包含Sepal的列
select(iris_df, starts_with("Sepal"))
#結(jié)果會返回 Sepal.Length 和Sepal.Width這兩列的值
#選取變量名前綴不包含Sepal的列
select(iris_df, -starts_with("Sepal"))
#結(jié)果會返回 Petal.Length、 Petal.Width 和 Species這三列的值

#選取變量名后綴包含Length的列
select(iris_df, ends_with("Length"))
#結(jié)果會返回 Sepal.Length和 Petal.Length這兩列的值

#選取變量名中包含eta的列
select(iris_df, contains("eta"))
#結(jié)果會返回 Petal.Length 和 Petal.Width這兩列值

#選取變量名中不包含eta的列
select(iris_df, -contains("eta"))
#結(jié)果會返回 Sepal.Length、Sepal.Width 和 Species這三列值

#正則表達式匹配,返回變量名中包含t的列
select(iris_df, matches(".t."))
#返回Sepal.Length、Sepal.Width、Petal.Length和 Petal.Width這四列值

# 使用one_of函數(shù)選擇字符向量中的列,下面兩個函數(shù)的結(jié)果是一致的
select(iris_df, one_of(c("Sepal.Length", "Sepal.Width")))
select(iris_df,Sepal.Length,Sepal.Width)
#返回Sepal.Length和Sepal.Width這兩列值

#返回所有列,一般調(diào)整數(shù)據(jù)集中變量順序時使用
select(iris_df, everything())

#調(diào)整列順序,把Species列放到最前面,作為第一列
select(iris_df, Species, everything())

#重命名列Species,返回的子數(shù)據(jù)集只包含重命名的spec列
select(iris_df, spec = Species)

#將列Species重命名為spec,并返回全部列
rename(iris_df, spec = Species)

6. mutate函數(shù)

對于數(shù)據(jù)集中的列進行運算,并添加到數(shù)據(jù)集中。原數(shù)據(jù)集行名稱會被過濾掉。transmute()函數(shù)作用與之類似,但是只返回新變量。

#計算新列wt_kg和wt_t,并添加新列到原數(shù)據(jù)集中(最后兩列)
mutate(mtcars_df, wt_kg = wt * 453.592, wt_t = wt_kg / 1000)

#計算新列wt_kg和wt_t,返回對象中只包含新列
transmute(mtcars_df, wt_kg = wt * 453.592, wt_t = wt_kg / 1000)

7. distinct函數(shù)

用于對數(shù)據(jù)集去重,返回?zé)o重復(fù)的行,類似于unique(),但是速度更快。原數(shù)據(jù)集行名稱會被過濾掉。

#設(shè)置隨機數(shù)種子
set.seed(1) 
#構(gòu)建一個簡單的數(shù)據(jù)集
df <- data.frame(x = sample(3,10, rep = TRUE), y = sample(c(2,3,4),10, rep = TRUE))
df

#以兩個變量作為去重標準,即x和y均相同的觀測會被剔掉重復(fù)的,只保留一個,返回去重后的數(shù)據(jù)。下面兩個函數(shù)返回的結(jié)果是一致的:
distinct(df) 
distinct(df, x, y) 

#以變量x去重,只返回去重后的x值
distinct(df, x)

#以變量x去重,并返回所有變量
distinct(df, x, .keep_all = TRUE)

#對變量運算后的結(jié)果去重 
distinct(df, multi=x*y)

8. summarize函數(shù)

對數(shù)據(jù)框調(diào)用函數(shù)進行匯總操作。

#返回數(shù)據(jù)框中變量wt的最大值及最小值
summarise(mtcars_df, max(wt), min(wt))

9.sample()函數(shù)

sample函數(shù)可以完成隨機抽樣處理
size 抽取樣本的數(shù)目
replace 如果為F(默認),則是不重復(fù)抽樣,此時size不能大于x的長度;
如果為T,則是重復(fù)抽樣,此時size允許大于x的長度

#sample_n函數(shù)的例子
set.seed(1)

#隨機無重復(fù)的取15行數(shù)據(jù)
sample_n(mtcars_df,15)

#隨機有重復(fù)的取100行數(shù)據(jù)
sample_n(mtcars_df, 100, replace = TRUE)

#隨機無重復(fù)的以 qsec值做權(quán)重抽取5行數(shù)據(jù)。如果某一行數(shù)據(jù)其對應(yīng)的qsec值越大,那這一行數(shù)據(jù)被抽中的可能性也會越大
sample_n(mtcars_df, 5, weight =  qsec)

#sample_frac函數(shù)的例子
set.seed(1)

#默認size=1,相當(dāng)于對全部數(shù)據(jù)無重復(fù)重新抽樣
sample_frac(mtcars)

#隨機無重復(fù)的取30%的數(shù)據(jù)
sample_frac(mtcars_df, 0.3) 

#隨機有重復(fù)的取總行數(shù)1.2倍的數(shù)據(jù)
sample_frac(mtcars_df, 1.2, replace = TRUE)

#隨機無重復(fù)的以1/qsec值做權(quán)重取30%的數(shù)據(jù)
sample_frac(mtcars_df, 0.3, weight = 1/qsec)

10. group_by()函數(shù)

用于對數(shù)據(jù)集按照給定變量分組,返回分組后的數(shù)據(jù)集。

#使用變量gear對mtcars分組,返回分組后數(shù)據(jù)集。但是此時的by_gear數(shù)據(jù)集的結(jié)構(gòu)與原始的mtcars_df相同。
by_gear <- group_by(mtcars_df, gear)

#返回每個分組中最大qsec所在的行
filter(by_gear, qsec == max(qsec))

#返回每個分組中變量名包含d的列,始終返回分組列g(shù)ear
select(by_gear, contains("d"))

#使用qsec對每個分組排序
arrange(by_gear,  qsec)

#對每個分組無重復(fù)的取3行記錄
sample_n(by_gear, 3)

#返回每個分組的記錄數(shù)
summarise(by_gear, n())

#求每個分組中disp和hp的均值
summarise(by_gear, mean(disp), mean(hp))

#返回每個分組中disp第二個值(不是第二大的值)
summarise(by_gear, nth(disp,2))

#獲取分組數(shù)據(jù)集所使用的分組變量
groups(by_gear)

#ungroup從數(shù)據(jù)框中移除組合信息(因此返回的分組變量為NULL) 
groups(ungroup(by_gear)) 

group_indices(mtcars_df, gear)
by_gear <- group_by(mtcars_df, gear)

#返回每個分組中的樣本記錄數(shù)。下面三個函數(shù)都能達到同樣的目的:
group_size(by_gear)
summarise(by_gear, n())
table(mtcars$gear)

#返回所分的組數(shù)
n_groups(by_gear)
length(group_size(by_gear))

#使用count對分組計數(shù),數(shù)據(jù)已按變量分組
count(mtcars_df,gear)

#使用tally對分組計數(shù),需要使用group_by分組
by_gear <- group_by(mtcars_df, gear)
tally(by_gear) 

#按gear分組,并對分組數(shù)據(jù)計算變量的mpg的和
count(mtcars_df,gear, wt = mpg)

tally(by_gear, wt = mpg)

11. %>%連接符

“%>%”這個管道函數(shù)把左件的值發(fā)送給右件的表達式,并作為右件表達式函數(shù)的第一個參數(shù)。

result <- flights %>%
  #將flights數(shù)據(jù)集傳給下面的group_by函數(shù)
  group_by(year, month, day) %>%
  select(arr_delay, dep_delay) %>%
  summarise(
    arr = mean(arr_delay, na.rm = TRUE),
    dep = mean(dep_delay, na.rm = TRUE)
  ) %>%
  filter(arr > 30 | dep > 30)
head(result)

a1 <- group_by(flights, year, month, day)
a2 <- select(a1, arr_delay, dep_delay)
a3 <- summarise(a2,
                arr = mean(arr_delay, na.rm = TRUE),
                dep = mean(dep_delay, na.rm = TRUE))
a4 <- filter(a3, arr > 30 | dep > 30)

管道函數(shù)還可以用在自定義函數(shù)(function)中,比如我們定義一個對向量中的數(shù)求整后取絕對值求和的函數(shù)。

## 一般代碼:

f1=function(x)sum(abs(round(x)))

## 管道函數(shù)代碼

f2=.%>% round %>% abs %>% sum

%<>% 在%>%的基礎(chǔ)上,會把右件的最終返回值返回給左件(注意是最終)。
a %in% table
a值是否包含于table中,為真輸出TURE,否者輸出FALSE。

參考:

  1. 陳興棟、張鐵軍、劉振球老師《R語言與數(shù)據(jù)清洗》
  2. Introduction to dplyr
  3. https://dplyr.tidyverse.org/
  4. R語言數(shù)據(jù)處理利器——dplyr簡介
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容