https://github.com/hbctraining/Intro-to-R
Tidyverse套件旨在共同努力怔檩,使通用數(shù)據(jù)科學(xué)的操作更加人性化讯壶。這些包具有數(shù)據(jù)規(guī)整暖侨,清洗剧蚣,讀/寫(xiě)提前,解析和可視化等功能吗货。免費(fèi)電子書(shū)R for Data Science詳細(xì)描述了可用工具的實(shí)例以及它們?nèi)绾螀f(xié)同工作。我們將探討使用這些軟件包的基本語(yǔ)法狈网,以及使用'dplyr'軟件包進(jìn)行數(shù)據(jù)規(guī)整的特定函數(shù)宙搬,使用'tidyr'軟件包清洗數(shù)據(jù)以及使用'ggplot2'軟件包進(jìn)行數(shù)據(jù)可視化。
這些包都使用相同的代碼風(fēng)格拓哺,即所有函數(shù)名和參數(shù)的格式均為snake_case
勇垛。詳見(jiàn)http://style.tidyverse.org/。
1.下載示例數(shù)據(jù)
我們將引入一個(gè)包含差異表達(dá)式分析結(jié)果的新文件作為示例數(shù)據(jù)士鸥。下載地址:https://github.com/hbctraining/Training-modules/raw/master/Visualization_in_R/data/Mov10oe_DE_results.csv 將其下載到之前的data
文件夾中(選擇Save Link As
或Download Linked File As
)窥摄。下載成功后可在RStudio“文件”選項(xiàng)卡的data
文件夾中看到它。
2.將示例數(shù)據(jù)讀取進(jìn)R
讀取剛下載的新文件并加載tidyverse
:
res_tableOE <- read.csv(file = "data/Mov10oe_DE_results.csv", row.names = 1)
library(tidyverse)
Tidyverse基礎(chǔ)知識(shí)
Tidyverse軟件包套件向用戶介紹了一組數(shù)據(jù)結(jié)構(gòu)础淤,函數(shù)和操作符崭放,以便更直觀地處理數(shù)據(jù),但與R base的工作方式略有不同鸽凶。管道和tibble是接下來(lái)要關(guān)注的兩個(gè)重要的新概念币砂。
(1) 管道
長(zhǎng)串的R命令讓人想退縮。此外玻侥,嘗試?yán)斫饩哂性S多嵌套函數(shù)的代碼可能會(huì)令人困惑决摧。
為了使R代碼更具人性化,Tidyverse工具使用%>%
從magrittr
包中獲取的管道凑兰,現(xiàn)在dplyr
是Tidyverse自動(dòng)安裝的軟件包的一部分掌桩。管道允許將前一個(gè)命令的輸出用作另一個(gè)命令的輸入,而不是使用嵌套函數(shù)姑食。
注意:寫(xiě)入管道的快捷方式是<kbd style="box-sizing: border-box; font-family: monospace, monospace; font-size: 1em;">shift</kbd>+ <kbd style="box-sizing: border-box; font-family: monospace, monospace; font-size: 1em;">command</kbd>+<kbd style="box-sizing: border-box; font-family: monospace, monospace; font-size: 1em;">M</kbd>
使用管道運(yùn)行多個(gè)命令的示例:
## A single command
sqrt(83)
## Base R method of running more than one command
round(sqrt(83), digit = 2)
## Running more than one command with piping
sqrt(83) %>% round(digit = 2)
管道代表了一種更簡(jiǎn)單的編寫(xiě)和解密R代碼的方式波岛,因此我們將在可能的情況下利用它,因?yàn)槲覀儗⑼瓿墒O碌恼n程音半。
練習(xí)
replicate
從metadata
數(shù)據(jù)框中提取列(使用$
表示法)并將值保存到名為的向量中rep_number
则拷。-
使用pipe(
%>%
)在一行中執(zhí)行兩個(gè)步驟:- 轉(zhuǎn)
rep_number
進(jìn)一個(gè)因素贡蓖。 - 使用該
head()
函數(shù)返回rep_number
因子的前六個(gè)值。
- 轉(zhuǎn)
(2)Tibbles
所述的核心組件tidyverse是tibble煌茬。Tibbles是標(biāo)準(zhǔn)的現(xiàn)代返工data.frame
斥铺,有一些內(nèi)部改進(jìn)使代碼更可靠。它們是數(shù)據(jù)框坛善,但不遵循所有相同的規(guī)則晾蜘。例如,tibbles可以包含列名的數(shù)字/符號(hào)眠屎,這在基數(shù)R中通常不允許笙纤。
重要提示:tidyverse對(duì)行名稱非常了解。這些軟件包堅(jiān)持要求所有列數(shù)據(jù)(例如data.frame
)被平等對(duì)待组力,并且rownames
應(yīng)該棄用特殊的列名稱省容。Tibble提供了簡(jiǎn)單的實(shí)用程序函數(shù)來(lái)處理rownames:rownames_to_column()
和column_to_rownames()
×亲郑可以找到更多有關(guān)處理元組中行名的幫助:
help("rownames", "tibble")
可以使用tibble()
函數(shù)直接創(chuàng)建Tibbles腥椒,也可以使用數(shù)據(jù)幀轉(zhuǎn)換為數(shù)據(jù)幀as_tibble(name_of_df)
。
注意:該函數(shù)
as_tibble()
將忽略行名稱候衍,因此如果需要表示行名稱的列笼蛛,rownames_to_column(name_of_df)
則應(yīng)在將data.frame轉(zhuǎn)換為tibble之前運(yùn)行該函數(shù)。此外蛉鹿,as_tibble()
默認(rèn)情況下不會(huì)將字符向量強(qiáng)制轉(zhuǎn)換為因子滨砍。
練習(xí)
df_tibble
使用tibble()
函數(shù)組合向量species
和創(chuàng)建一個(gè)tibbleglengths
。注意:您的glengths
向量可能與長(zhǎng)度不同species
妖异,因此您需要使用適當(dāng)大小的子集惋戏。將
metadata
數(shù)據(jù)框更改為名為的tibblemeta_tibble
。使用該rownames_to_column()
函數(shù)保留與使用%>%
和as_tibble()
函數(shù)結(jié)合的rownames 他膳。
tibble有個(gè)很好的特點(diǎn)响逢,當(dāng)一個(gè)變量打印到屏幕時(shí),默認(rèn)情況下它只會(huì)顯示前10行和適合屏幕的列棕孙。這樣很方便舔亭,不必用head()
查看數(shù)據(jù)集了。
# Default printing of data.frame
rpkm_data
# Default printing of tibble
rpkm_data %>%
rownames_to_column() %>%
as_tibble()
注意:如果需要查看更多行列蟀俊,
print()
函數(shù)可以更改顯示的行數(shù)或列數(shù)钦铺。# Printing of tibble with print() - change defaults rpkm_data %>% rownames_to_column() %>% as_tibble() %>% print(n = 20, width = Inf)
Tidyverse tools
雖然Tidyverse套件中的所有工具都值得進(jìn)行更深入的探索,但本課程僅研究我們將最常用于數(shù)據(jù)規(guī)整和清洗的工具肢预。
注意:大量的tidyverse函數(shù)將同時(shí)使用tibbles和dataframes矛洞,輸出的數(shù)據(jù)結(jié)構(gòu)將與輸入相同床未。但是比勉,有些函數(shù)會(huì)返回一個(gè)tibble(沒(méi)有行名)瞧预,無(wú)論是否提供了tibble或dataframe弊决。
Tidyverse之Dplyr
tidyverse中最有用的工具是dplyr窑邦。它用于數(shù)據(jù)規(guī)整擅威,堪比瑞士軍刀。dplyr有許多方便的函數(shù)冈钦,非常建議將它用于數(shù)據(jù)分析:
-
select()
提取列并返回一個(gè)tibble郊丛。 -
arrange()
更改行的順序。 -
filter()
根據(jù)其值選擇行瞧筛。 -
mutate()
添加作為現(xiàn)有變量函數(shù)的新變量厉熟。 -
rename()
輕松更改列的名稱 -
summarise()
將多個(gè)值減少到單個(gè)摘要。 -
pull()
提取單個(gè)列作為向量较幌。 -
_join()
的兩個(gè)數(shù)據(jù)幀合并到一起的函數(shù)組揍瑟,包括(inner_join()
,left_join()
乍炉,right_join()
绢片,和full_join()
)。
注意:dplyr在2017年進(jìn)行了大規(guī)模修訂岛琼,將版本從0.5切換到0.7底循。如果在線查閱其他dplyr教程,請(qǐng)注意2017年之前的資料已過(guò)時(shí)槐瑞。尤其是用dplyr編寫(xiě)函數(shù)的部分(請(qǐng)參閱下面的注釋部分)熙涤。
select()
要從一個(gè)tibble中提取列,用select()
函數(shù)困檩。
# Convert the res_tableOE data frame to a tibble
res_tableOE <- res_tableOE %>%
rownames_to_column(var="gene") %>%
as_tibble()
# extract selected columns from res_tableOE
res_tableOE %>%
select(gene, baseMean, log2FoldChange, padj)
相反祠挫,可以使用否定選擇刪除不需要的列。
res_tableOE %>%
select(-c(lfcSE, stat, pvalue))
## # A tibble: 23,368 x 4
## gene baseMean log2FoldChange padj
## <chr> <dbl> <dbl> <dbl>
## 1 1/2-SBSRNA4 45.6520399 0.266586547 2.708964e-01
## 2 A1BG 61.0931017 0.208057615 3.638671e-01
## 3 A1BG-AS1 175.6658069 -0.051825739 7.837586e-01
## 4 A1CF 0.2376919 0.012557390 NA
## 5 A2LD1 89.6179845 0.343006364 7.652553e-02
## 6 A2M 5.8600841 -0.270449534 2.318666e-01
## 7 A2ML1 2.4240553 0.236041349 NA
## 8 A2MP1 1.3203237 0.079525469 NA
## 9 A4GALT 64.5409534 0.795049160 2.875565e-05
## 10 A4GNT 0.1912781 0.009458374 NA
## # ... with 23,358 more rows
將這個(gè)tibble保存為一個(gè)名為sub_res
的新變量:
sub_res <- res_tableOE %>%
select(-c(lfcSE, stat, pvalue))
arrange()
請(qǐng)注意悼沿,現(xiàn)在行是按symbol排序茸歧。用arrange()
按照adjusted P value進(jìn)行排序。
arrange(sub_res, padj)
## # A tibble: 23,368 x 4
## gene baseMean log2FoldChange padj
## <chr> <dbl> <dbl> <dbl>
## 1 MOV10 21681.7998 4.7695983 0.000000e+00
## 2 H1F0 7881.0811 1.5250811 2.007733e-162
## 3 HSPA6 168.2522 4.4993734 1.969313e-134
## 4 HIST1H1C 1741.3830 1.4868361 5.116720e-101
## 5 TXNIP 5133.7486 1.3868320 4.882246e-90
## 6 NEAT1 21973.7061 0.9087853 2.269464e-83
## 7 KLF10 1694.2109 1.2093969 9.257431e-78
## 8 INSIG1 11872.5106 1.2260848 8.853278e-70
## 9 NR1D1 969.9119 1.5236259 1.376753e-64
## 10 WDFY1 1422.7361 1.0629160 1.298076e-61
## # ... with 23,358 more rows
filter()
只保留表達(dá)的基因(baseMean
高于0)显沈,adjusted P value小于0.01软瞎。可以filter()
一個(gè)命令中放入多個(gè)條件篩選拉讯。
sub_res %>%
filter(baseMean > 0 & padj < 0.01)
## # A tibble: 4,959 x 4
## gene baseMean log2FoldChange padj
## <chr> <dbl> <dbl> <dbl>
## 1 A4GALT 64.5 0.798 2.40e- 5
## 2 AAGAB 2614\. -0.390 1.68e-11
## 3 AAMP 3157\. -0.380 9.11e-13
## 4 AARS 3690\. 0.167 2.10e- 3
## 5 AARS2 2255\. -0.204 3.77e- 4
## 6 AASDHPPT 3561\. -0.293 3.79e- 7
## 7 AASS 1018\. 0.347 7.94e- 5
## 8 AATF 2613\. -0.290 1.97e- 7
## 9 ABAT 384\. 0.384 1.99e- 4
## 10 ABCA1 108\. 0.833 4.19e- 7
## # ... with 4,949 more rows
mutate()
mutate()
使您可以從現(xiàn)有列創(chuàng)建新列涤浇。讓我們?yōu)槊總€(gè)基因生成log10的baseMeans計(jì)算。
sub_res %>%
mutate(log10BaseMean = log10(baseMean)) %>%
select(gene, baseMean, log10BaseMean)
## # A tibble: 23,368 x 3
## gene baseMean log10BaseMean
## <chr> <dbl> <dbl>
## 1 1/2-SBSRNA4 45.7 1.66
## 2 A1BG 61.1 1.79
## 3 A1BG-AS1 176\. 2.24
## 4 A1CF 0.238 -0.624
## 5 A2LD1 89.6 1.95
## 6 A2M 5.86 0.768
## 7 A2ML1 2.42 0.385
## 8 A2MP1 1.32 0.121
## 9 A4GALT 64.5 1.81
## 10 A4GNT 0.191 -0.718
## # ... with 23,358 more rows
rename()
快速重命名現(xiàn)有列rename()
魔慷。語(yǔ)法是new_name
= old_name
只锭。
sub_res %>%
rename(symbol = gene)
## # A tibble: 23,368 x 4
## symbol baseMean log2FoldChange padj
## <chr> <dbl> <dbl> <dbl>
## 1 1/2-SBSRNA4 45.7 0.268 0.264
## 2 A1BG 61.1 0.209 0.357
## 3 A1BG-AS1 176\. -0.0519 0.781
## 4 A1CF 0.238 0.0130 NA
## 5 A2LD1 89.6 0.345 0.0722
## 6 A2M 5.86 -0.274 0.226
## 7 A2ML1 2.42 0.240 NA
## 8 A2MP1 1.32 0.0811 NA
## 9 A4GALT 64.5 0.798 0.0000240
## 10 A4GNT 0.191 0.00952 NA
## # ... with 23,358 more rows
pull()
在最近的dplyr 0.7更新中,pull()
添加了作為向量訪問(wèn)列數(shù)據(jù)的快速方法院尔。這在與管道操作符連用非常方便蜻展。
# Extract first 10 values from the gene column
pull(sub_res, gene) %>% head()
_join()
Dplyr具有一組強(qiáng)大的連接操作喉誊,它們基于兩個(gè)數(shù)據(jù)框中存在的變量或變量集將一對(duì)數(shù)據(jù)框連接在一起,這些變量或變量集唯一地標(biāo)識(shí)所有觀察纵顾。這些變量稱為鍵伍茄。
inner_join
:只有兩個(gè)數(shù)據(jù)集中存在鍵的行將連接在一起。left_join
:保留第一個(gè)數(shù)據(jù)框中的所有行施逾,連接第二個(gè)數(shù)據(jù)框中具有鍵的行敷矫。right_join
:保留第二個(gè)數(shù)據(jù)框中的所有行,連接第一個(gè)數(shù)據(jù)框中具有鍵的行汉额。full_join
:保留兩個(gè)數(shù)據(jù)集中的所有行曹仗,沒(méi)有匹配鍵的行產(chǎn)生NA值。
為了練習(xí)連接功能蠕搜,創(chuàng)建如下示例數(shù)據(jù):
描述:對(duì)于一個(gè)研究項(xiàng)目怎茫,我們?cè)儐?wèn)健康志愿者和癌癥患者關(guān)于他們的飲食和鍛煉的問(wèn)題。我們還為每個(gè)人收集了血液工作妓灌,每個(gè)人都獲得了一個(gè)獨(dú)特的身份證轨蛤。創(chuàng)建數(shù)據(jù)框
behavior
和blood
,復(fù)制/粘貼以下代碼:-
數(shù)據(jù):
# Creating behavior dataframe ID <- c(546, 983, 042, 952, 853, 061) diet <- c("veg", "pes", "omni", "omni", "omni", "omni") exercise <- c("high", "low", "low", "low", "med", "high") behavior <- data.frame(ID, diet, exercise) # Creating blood dataframe ID <- c(983, 952, 704, 555, 853, 061, 042, 237, 145, 581, 249, 467, 841, 546) blood_levels <- c(43543, 465, 4634, 94568, 134, 347, 2345, 5439, 850, 6840, 5483, 66452, 54371, 1347) blood <- data.frame(ID, blood_levels)
并非所有血液ID都有相關(guān)的behavior信息旬渠。使用_join
函數(shù)族俱萍,練習(xí)加入連接數(shù)據(jù)框的不同選項(xiàng)。
要僅連接兩個(gè)數(shù)據(jù)框中都有的ID告丢,可以使用inner_join()
函數(shù):
# Inner join
inner_join(blood, behavior)
或者枪蘑,如果想要返回所有血液ID,但只包括匹配的行為ID岖免,我們可以使用以下left_join()
功能:
# Left join
left_join(blood, behavior)
使用 right_join()
也可以做同樣的事岳颇,所有行為ID和匹配的血液ID:
# Right join
right_join(blood, behavior)
最后,無(wú)論是否存在匹配的鍵(ID)颅湘,都可以兩個(gè)數(shù)據(jù)框出現(xiàn)的所有ID:
# Full join
full_join(blood, behavior)
注意:如果兩個(gè)數(shù)據(jù)框中的名稱不具有相同的列名话侧,則需要包含
by
參數(shù)。例如:inner_join(df1, df2, by = c("df1_colname" = "df2_colname"))
Tidyverse 之Tidyr
Tidyr的目的是擁有組織良好或整潔的數(shù)據(jù)闯参,Tidyverse將tidydata其定義為:
- 每個(gè)變量作為一列
- 每個(gè)觀測(cè)作為一行
- 每個(gè)值占一個(gè)單元格
Tidyr有兩個(gè)主要函數(shù)瞻鹏,gather()
和spread()
。這些函數(shù)允許在長(zhǎng)數(shù)據(jù)格式和寬數(shù)據(jù)格式之間進(jìn)行轉(zhuǎn)換鹿寨。下游分析決定所需的數(shù)據(jù)格式新博。
gather()
該gather()
函數(shù)將寬數(shù)據(jù)格式更改為長(zhǎng)數(shù)據(jù)格式。當(dāng)使用'ggplot2'將所有值繪制到單個(gè)列中時(shí)脚草,此函數(shù)特別有用赫悄。
要使用此函數(shù),需要提供原數(shù)據(jù)框中需要聚合的多個(gè)列名。然后使用key
參數(shù)提供原數(shù)據(jù)框列名聚成的新列的名稱埂淮,使用value
參數(shù)提供所有值聚合成的的列的名稱姑隅。
rpkm_data_tb <- rpkm_data %>%
rownames_to_column() %>%
as_tibble()
gathered <- rpkm_data_tb %>%
gather(colnames(rpkm_data_tb)[2:13],
key = "samplename",
value = "rpkm")
spread()
spread()
函數(shù)與gather()
函數(shù)相反。key
列的類別將成為單獨(dú)的新列倔撞,value
列中的值將根據(jù)關(guān)聯(lián)的key
列進(jìn)行拆分讲仰。
gathered %>%
spread(key = "samplename",
value = "rpkm")
Tidyverse之Stringr
Stringr是一個(gè)處理字符序列或字符串的強(qiáng)大工具。stringr中有許多函數(shù)可用于處理字符串误窖,但我們會(huì)介紹一些最有用的函數(shù):
-
str_c()
將字符串連接在一起 -
str_split()
通過(guò)指定分隔符來(lái)拆分字符串 -
str_sub()
從特定位置的字符串中提取字符 -
str_replace()
用另一個(gè)字符串替換現(xiàn)有字符串 -
str_to_()
組功能改變了的字符串的情況下的功能叮盘,包括str_to_upper()
秩贰,str_to_lower()
和str_to_title()
-
str_detect()
標(biāo)識(shí)向量中的每個(gè)元素中是否存在模式 -
str_subset()
僅返回與模式匹配的元素
除了其他字符串函數(shù)之外霹俺,為了幫助使用這些函數(shù),還有一個(gè)方便的字符串備忘單毒费。
str_c()
str_c()
函數(shù)將值與指定的分隔符連接在一起丙唧。collapse
參數(shù)指定是否將多個(gè)對(duì)象合并為單個(gè)字符串。
metadata <- metadata %>%
mutate(sample = str_c(genotype, celltype, replicate, sep = "_"))
str_split()
與str_c()
相反觅玻,str_split()
將基于指定的分隔符分隔值想际。
metadata %>%
pull(sample) %>%
str_split("_")
str_sub()
為了從字符串中提取字符,str_sub()
函數(shù)可按照位置提取的字符串中:
metadata %>%
pull(sample) %>%
str_sub(start = 1, end = 8)
要用另一個(gè)字符串替換現(xiàn)有字符串溪厘,使用str_replace()
函數(shù):
str_replace()
metadata %>%
pull(celltype) %>%
str_replace("typeA", "typeP")
默認(rèn)情況下胡本,str_replace()
只會(huì)替換每個(gè)元素/組件中的第一個(gè)匹配。如果你想替換所有匹配畸悬,那么就用str_replace_all()
函數(shù)侧甫。
str_to_()
在數(shù)據(jù)整理過(guò)程中,需要確保列的所有值都具有相同的大小寫(xiě)蹋宦,因?yàn)镽區(qū)分大小寫(xiě)披粟。使用str_to_
函數(shù)族,包括str_to_upper()
冷冗,str_to_lower()
和str_to_title()
守屉,可以很簡(jiǎn)單的修改任何值的大小寫(xiě)。
metadata %>%
pull(genotype) %>%
str_to_upper()
metadata %>%
pull(genotype) %>%
str_to_lower()
metadata %>%
pull(genotype) %>%
str_to_title()
最后兩個(gè)函數(shù)蒿辙,str_detect()
和str_subset()
需要一個(gè)模式來(lái)匹配拇泛。通常在字符串中指定模式時(shí),使用正則表達(dá)式(regexps)來(lái)描述思灌。使用正則表達(dá)式時(shí)俺叭,有一些有用的特殊字符,有關(guān)這些的詳細(xì)信息可以在R for Data Science一書(shū)和Duke的材料(http://www2.stat.duke.edu/~cr173/Sta523_Fa16/regex.html)中找到习瑰,我們?cè)谶@里列出了一些常用字符:
-
"."
:匹配每個(gè)字符(如果想匹配.
字符绪颖,就需要使用\\.
來(lái)轉(zhuǎn)換) -
"^characters"
:匹配字符串的開(kāi)頭 -
"characters$"
:匹配字符串的結(jié)尾 -
"[characters]"
:匹配[]內(nèi)的任何字符 -
"[ ^characters]"
:匹配不在[]內(nèi)的任何字符 -
"[A-z0-9]"
:匹配任何字母或數(shù)字 -
"*"
:匹配零次或多次
str_detect()
str_detect()
函數(shù)標(biāo)識(shí)向量的每個(gè)元素中是否存在模式。此函數(shù)返回一個(gè)邏輯值,表示每個(gè)元素是否與模式匹配柠横。
idx <- str_detect(metadata$sample, "typeA_1")
# Allows for subsetting dataframes using the logical operators
metadata[idx, ]
str_subset()
要僅返回與模式匹配的值窃款,用str_subset()
函數(shù):
metadata %>%
pull(sample) %>%
str_subset("typeA_1")
編程說(shuō)明
在處理過(guò)程中,tidyverse包用rlang在base R語(yǔ)言上構(gòu)建牍氛,這是對(duì)函數(shù)如何處理變量名和評(píng)估參數(shù)的全盤(pán)重做晨继。這是通過(guò)tidyeval
框架實(shí)現(xiàn)的,該框架使用tidy evaluation
與命令操作交互搬俊。這超出了本課程的范圍紊扬,但在Programming with dplyr(http://dplyr.tidyverse.org/articles/programming.html)中有詳細(xì)解釋,可以了解這些新工具與基礎(chǔ)base R的表現(xiàn)有何不同唉擂。
其他資源
- R for Data Science(http://r4ds.had.co.nz/)
- teach the tidyverse(http://varianceexplained.org/r/teach-tidyverse/)
- tidy style guide(http://style.tidyverse.org/)
微信公眾號(hào)生信星球同步更新我的文章餐屎,歡迎大家掃碼關(guān)注!
我們有為生信初學(xué)者準(zhǔn)備的學(xué)習(xí)小組,點(diǎn)擊查看??
想要參加我的線上線下課程玩祟,也可加好友咨詢??
如果需要提問(wèn)腹缩,請(qǐng)先看生信星球答疑公告