【R語言】從Function到lapply,再到future.apply

寫在前面
上一節(jié)介紹了For循環(huán)在科研上的小例子轨香,本節(jié)來講述一下自己編寫函數(shù)的樂趣。

1.引入

結(jié)構(gòu)

function.name <- function(arguments){
  computations_on_the_arguments
}

舉例一:
傳入兩個(gè)參數(shù)幼东,計(jì)算x的y次方加上1臂容。

> yourSecondfun <- function(a,b){
  a^b+1
  }
>  yourSecondfun(5,3)
>  126

舉例二:
計(jì)算乘方和乘積,同時(shí)返回根蟹。默認(rèn)只返回最后一個(gè)參數(shù)脓杉,如果想返回多個(gè)參數(shù),要使用return()函數(shù)简逮。

doubleget <- function(x,y){
  a <- x^y
  b <- x*y
  return(c(a,b))
}
doubleget(2,3)

2.For循環(huán)和函數(shù)的相互轉(zhuǎn)換

For循環(huán)根據(jù)TCGA_id第14和15位的數(shù)字來判斷是tumor還是sample球散。

rm(list = ls())
load(file = "data/TCGA_ggplot.Rdata")
metadata <- data.frame(TCGA_id=rownames(exprSet)) #轉(zhuǎn)換成數(shù)據(jù)框
for (i in 1:length(metadata[,1])) {
  num <- as.numeric(substring(metadata[i,1],14,15)) 
  if (num %in% seq(1,9)) {metadata[i,2] = "Tumor"} 
  if (num %in% seq(10,29)) {metadata[i,2] = "Normal"} 
}
colnames(metadata) <- c("TCGA_id","sample")

改寫成函數(shù),使其輸入一個(gè)TCGA_id散庶,就能判斷ID屬于是tumor還是sample蕉堰。

tell_me_sample <- function(TCGAID){
    num <- as.numeric(substring(TCGAID,14,15)) 
    if (num %in% seq(1,9)) {sample = "Tumor"} 
    if (num %in% seq(10,29)) {sample = "Normal"}
    return(sample)
  
}
tell_me_sample("TCGA-AC-A3OD-01B-06R-A22O-07")
tell_me_sample("TCGA-BH-A0B5-11A-23R-A12P-07")
tell_me_sample(metadata[1,1])
tell_me_sample(metadata[3,1])

3.寫一個(gè)作圖函數(shù)

> rm(list = ls())
> load(file = "data/TCGA_ggplot.Rdata")

> my_comparisons <- list(
  c("LumA", "Normal"),
  c("LumB", "Normal"),
  c("Her2", "Normal"),
  c("Basal", "Normal")
)
> library(ggpubr)
> ggboxplot(
  exprSet, x = "subgroup", y = "ESR1",
  color = "subgroup", palette = c("#00AFBB", "#E7B800", "#FC4E07","#A687D8", "#89E4A4"),
  add = "jitter"
)+
  stat_compare_means(comparisons = my_comparisons, method = "t.test")

畫圖代碼來源:https://mp.weixin.qq.com/s/AE3Rt3IoWAkhvPYtEiwWQg

改寫成函數(shù)的形式,使其輸入一個(gè)基因名悲龟,就可以拿到boxplot屋讶。

> subgroup_plot <- function(gene){
  ggboxplot(
    exprSet,x='subgroup',y=gene,
    color = 'subgroup',palette = c("#00AFBB","#E7B800","#FC4E07","#A687D8","#89E4A4"),
    add = "jitter"
  )+
    stat_compare_means(comparisons = my_comparisons,method = "t.test")
}
> subgroup_plot("SAMD11")

> subgroup_plot("BRCA1")

4.lapply

基因和免疫浸潤的相關(guān)性分析

rm(list = ls())
load(file = "data/expr_immu_BRCA.Rdata")
gene <- "KLF5"
y <- as.numeric(expr_data[,gene])
### 批量操作的具體實(shí)現(xiàn)過程:
### 1.設(shè)定容器,最終生成的數(shù)據(jù)放在什么地方?
correlation <- data.frame()
### 2.批量把數(shù)據(jù)導(dǎo)出到容器
for(i in 1:length(colnames(immu_data))){
  ## 1.指示
  print(i)
  ## 2.計(jì)算
  dd = cor.test(as.numeric(immu_data[,i]),y,method="spearman")
  ## 3.填充
  correlation[i,1] = colnames(immu_data)[i]
  correlation[i,2] = dd$estimate
  correlation[i,3] = dd$p.value
}
### 修改名稱
colnames(correlation) <- c("cell","cor","p.value")

將上述代碼轉(zhuǎn)換成lapply+function的模式來計(jì)算躲舌。
lapply 以及do.call 的介紹:https://mp.weixin.qq.com/s/VvbZOXlefGGEcekYWl0ZbQ
三步走戰(zhàn)略丑婿。
第一步:寫出單次處理的function

mycor = function(x){
  dd = cor.test(as.numeric(immu_data[, x]),y,method ="spearman",exact=FALSE)
  data.frame(cell=x,cor=dd$estimate,p.value=dd$p.value)
}
### 測試函數(shù)功能
mycor("Activated B cell")

第二步:lapply批量作用于函數(shù),返回list

lapplylist = lapply(colnames(immu_data),mycor)

第三步:do.call 轉(zhuǎn)換list没卸。lapply填充的是列表+函數(shù)羹奉;do.call填充的是函數(shù)+列表。

cor_data <- do.call(rbind,lapplylist)

通過畫圖來展示數(shù)據(jù)結(jié)果约计。

library(dplyr)
library(ggplot2)
cor_data %>% 
  filter(p.value <0.05) %>% 
  ggplot(aes(cor,forcats::fct_reorder(cell,cor)))+
  geom_segment(aes(xend=0,yend=cell))+
  geom_point(aes(col=p.value,size=abs(cor)))+
  scale_colour_gradientn(colours=c("#7fc97f","#984ea3"))+
  #scale_color_viridis_c(begin = 0.5, end = 1)+
  scale_size_continuous(range =c(2,8))+
  theme_bw()+
  ylab(NULL)

如果熟練了诀拭,三步走可以變成一步。

cor_data <- do.call(rbind,lapply(colnames(immu_data),function(x){
  dd = cor.test(as.numeric(immu_data[,x]),y,method ="spearman",exact=FALSE)
  data.frame(cell=x,cor=dd$estimate,p.value=dd$p.value)
}))

5. 單基因的批量相關(guān)性分析

加載數(shù)據(jù)

rm(list = ls())
load(file = "data/TCGA_BRCA_exprSet_plot.Rdata")
test <- exprSet[1:10,1:10]

A.使用for循環(huán)來完成煤蚌。

##1.設(shè)定容器,最終生成的數(shù)據(jù)放在什么地方耕挨?
correlation <- data.frame()

##2.準(zhǔn)備數(shù)據(jù)
data <- exprSet[,-c(1,2,3)]
test <- data[1:10,1:10]

##3.獲取批量操作的范圍,應(yīng)該是個(gè)向量
genelist <- colnames(data)

##4.開始for循環(huán),批量執(zhí)行單次操作
gene <- "FOXA1"
genedata <- as.numeric(data[,gene])
for(i in 1:length(genelist)){
  ## 1.指示
  print(i)
  ## 2.計(jì)算
  dd = cor.test(genedata,as.numeric(data[,i]),method="spearman")
  ## 3.填充
  correlation[i,1] = gene
  correlation[i,2] = genelist[i]
  correlation[i,3] = dd$estimate
  correlation[i,4] = dd$p.value
}

colnames(correlation) <- c("gene1","gene2","cor","p.value")

B.使用function和lapply來完成细卧。

### 第1,寫出單次處理的function
mycor = function(i){
  dd = cor.test(genedata,as.numeric(data[,i]),method="spearman")
  data.frame(gene1=gene,gene2=i,cor=dd$estimate,p.value=dd$p.value)
}
### 測試函數(shù)功能
mycor("GATA3")

### 第2步lapply批量作用于函數(shù),返回list
system.time(lapplylist <- lapply(genelist,mycor))

### 第3步do.call 轉(zhuǎn)換list
cor_data <- do.call(rbind,lapplylist)
### 熟悉了可以寫成1步
cor_data <- do.call(rbind,lapply(genelist,function(i){
  dd = cor.test(genedata,as.numeric(data[,i]),method="spearman")
  data.frame(gene1=gene,gene2=i,cor=dd$estimate,p.value=dd$p.value)
}))

C.使用future_lapply + funcxtion
future_lapplylapply的不同之處在于筒占,前者可以調(diào)用電腦的多線程來工作贪庙,而后者只能用單線程。如果計(jì)算量不大的話翰苫,可能多線程工作還不如單線程省時(shí)止邮。
加載R包。

install.packages("future.apply")
library(future.apply)
plan(multisession) #查看電腦總共有多少線程

三步走戰(zhàn)略

### 第1,寫出單次處理的function
mycor = function(i){
  dd = cor.test(genedata,as.numeric(data[,i]),method="spearman")
  data.frame(gene1=gene,gene2=i,cor=dd$estimate,p.value=dd$p.value)
}
### 測試函數(shù)功能
mycor("GATA3")

### 第2步lapply批量作用于函數(shù)奏窑,返回list
### system.time(lapplylist <- lapply(genelist,mycor))
system.time(lapplylist <- future_lapply(genelist,mycor))

### 第3步do.call 轉(zhuǎn)換list
cor_data <- do.call(rbind,lapplylist)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末导披,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子埃唯,更是在濱河造成了極大的恐慌撩匕,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件墨叛,死亡現(xiàn)場離奇詭異止毕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)漠趁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門滓技,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人棚潦,你說我怎么就攤上這事令漂。” “怎么了丸边?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵叠必,是天一觀的道長。 經(jīng)常有香客問我妹窖,道長纬朝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任骄呼,我火速辦了婚禮共苛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蜓萄。我一直安慰自己隅茎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布嫉沽。 她就那樣靜靜地躺著辟犀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绸硕。 梳的紋絲不亂的頭發(fā)上堂竟,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天魂毁,我揣著相機(jī)與錄音,去河邊找鬼出嘹。 笑死席楚,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的税稼。 我是一名探鬼主播酣胀,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼娶聘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起甚脉,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤丸升,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后牺氨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體狡耻,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年猴凹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了夷狰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡郊霎,死狀恐怖沼头,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情书劝,我是刑警寧澤进倍,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站购对,受9級(jí)特大地震影響猾昆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜骡苞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一垂蜗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧解幽,春花似錦贴见、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至徘溢,卻和暖如春吞琐,著一層夾襖步出監(jiān)牢的瞬間捆探,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來泰國打工站粟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留黍图,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓奴烙,卻偏偏與公主長得像助被,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子切诀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容