徵得張敬信老師同意,本號將轉載張老師關於R語言tidyverse包一系列文章,為大家進行醫學研究提供助力。
來源:R&Python數據科學 知乎專欄
作者簡介:張敬信,高校數學教師,研究興趣:數學,數學建模,數據挖掘,機器學習,Matlab, R語言,Python,Mathematica,Latex
連結:https://www.zhihu.com/people/huc_zhangjingxin
前言Hadley 大神的 tidyverse 包,將數據處理和建模整個流程所涉及到的:讀入、清洗、重塑、匯總、可視化、探索、建模、結果展示的整個流程,都以一種「優雅」的方式整合到了一起。
我之前學了一遍 Hadley 的配套書《R for Data Science》,雖然比較系統全面,但重點部分有點過於基礎,實用性欠缺了點。最近偶然看到一個非常好且精煉的進階資料《Working in the Tidyverse》,主要以它為主,翻譯並學習記錄下來。
強烈建議大家,拋棄流傳甚廣的陳舊的數據操作方面的 R 語法,全面改用 tidyverse。
——————————————————————————————
下面先從第零篇,管道操作,開始。
一. 簡介magrittr 包引入了管道操作,能夠通過管道將數據從一個函數傳給另一個函數,從而用若干函數構成的管線依次變換你的數據。
先看一個例子,對數據集 warpbreaks,按分類變量 wool 和 tension 分組,對連續變量 breaks 做分組匯總,分別計算均值、中位數、標準差:
warpbreaks %>%
group_by(wool, tension) %>%
summarise_at(vars(breaks), list(~mean(.), ~median(.), ~sd(.)))
管道運算符%>%的意思是:將左邊的運算結果,以輸入的方式傳給右邊函數。若干個函數通過管道連結起來,叫做管線(pipeline)。
"ATMOSPHERE" %>% str_replace("SPHERE", "SQUARE") %>% str_to_lower() %>% print()
管線,也支持 Base R 函數:
month.abb %>% # 內置月份名縮寫的字符串
sample(6) %>%
tolower() %>%
paste0(collapse = "|")
使用管道的好處是:
(1)避免使用過多的中間變量;
(2)程序可讀性大大增強:
管道操作的過程,讀起來就是對原數據集依次進行一系列操作的過程。而非管道操作,讀起來與操作的過程是相反的,比如同樣實現上例:
paste0(tolower(sample(month.abb, 6)), collapse="|")
二. 使用管道操作管道默認將輸出傳給下一個函數的第1個參數
. <- c(1, 3, 4, 5, NA)
mean(., na.rm=TRUE)
c(1, 3, 4, 5, NA) %>% mean(., na.rm=TRUE)
c(1, 3, 4, 5, NA) %>% mean(na.rm = TRUE) # "."可以省略
2. 輸出可以在右邊使用多次
在右邊的函數調用中需要藉助".":
c(1, 3, 4, 5) %>% plot(., main=paste(., collapse=", "))
# 第1個"."可以省略, 其餘的"."不能省略
c(1, 3, 4, 5) %>% plot(main=paste(., collapse=", "))
3. 輸出傳給不是第1個參數
若函數的第1個參數不是接受數據,需要手動放置"."
# 錯誤做法
# iris %>% plot(Sepal.Width~Petal.Width) # 相當於
# plot(x=iris, y=Sepal.Width~Petal.Width)
# 正確做法
iris %>% plot(Sepal.Width~Petal.Width, data = .)
4. 管道中使用函數
(1) 有時候想在管道中使用匿名函數
month.abb %>% # 選擇子集
{.[1:3]}
# 等同於
month.abb %>%
(function(.) {.[1:3]})
(2) 也可以將整個管線定義為一個函數,需要將"."作為管線的第1個值,將整個管線賦值給一個名字(函數名)
random_sepal_data <- # 函數名
. %>% # 用"."作為管線的開始
select(Species, starts_with("Sepal")) %>%
sample_n(5) %>%
arrange(desc(Sepal.Length))
iris %>%
random_sepal_data()
注意:管線函數總是一元的,只能接受一個參數,而且在管線中參數為一個".";若要在管線內傳遞多個參數,需要用通常的方式 function() 定義函數。
5. 通常操作的管道函數
你可能想要用[ 或 [[ 或 $訪問"."的內容,例如選擇數據框的子集,查看直方圖中某個條形的值。可以用這些函數的前綴形式實現,但可讀性不好:
iris %>%
filter(Petal.Length>2, Petal.Width>2) %>%
`[[`("Sepal.Length") %>%
hist(main="Histogram of 'Sepal.Length' after subsetting")
magrittr 包提供了一些函數來實現這樣的操作,更多函數可用 ?extract 查閱。
iris %>%
head() %>%
extract(c("Sepal.Length","Sepal.Width")) # 提取列, 返回數據框
iris %>%
head() %>%
extract2("Sepal.Length") # 提取1列, 返回向量
注意:不同包中同名的函數,默認是選最近加載的包中的。建議用加前綴的方式「magrittr::」為這樣的函數指定包。
參考文獻:
1. Desi Quintans, Jeff Powell. Working in the Tidyverse. hiercourse.com/
2. Garrett Grolemund, Hadley Wickham. R for Data Science. r4ds.had.co.nz/