前情提要:今天不咕咕咕继续学习
part five来到 lapply 的高级应用部分future_lapply
目录
1.future_apply
library(future.apply)
plan(multisession)
message("outside>>how many cores can use now: ", nbrOfWorkers())
激活并查看并行核数
如果计算量不大的话,可能多线程工作还不如单线程省时。
一些并行计算的东西:
ibrary(future) #加载以后并激活多核后,可以直接运行Seurat
library(future.apply) #如果使用future_lapply时加载这个
plan(multisession) #激活多核 也可以选择激活的个数
plan(multisession, workers=5)
message("outside>>how many cores can use now: ", nbrOfWorkers()) #查看并行核数
plan(sequential) #关闭多核
plan("default") 也可以关多核
message("outside>>how many cores can use now: ", nbrOfWorkers())
Seurat单细胞分析R包中多个步骤支持多线程,比如 normalize, scale, find marker 等。
以下函数已被编写可以利用future 框架,如果设置适当的plan,将进行并行。
-
FindClusters() - if clustering over multiple resolutions
要运行并行版本,您只需要设置future 并照常调用FindMarkers()功能。
在任何平行模式下运行这些函数时,您将失去进度栏。plan(sequential)恢复原模式
2.批量计算基因相关性
rm(list = ls())
### 加载数据
load(file = "data/TCGA_BRCA_exprSet_plot.Rdata")
test <- exprSet[1:10,1:10];test
#######################
### A,FOR 循环
### 批量操作的具体实现过程:
##1.设定容器,最终生成的数据放在什么地方?
correlation <- data.frame()
##2.准备数据
data <- exprSet[,-c(1,2,3)]
test <- data[1:10,1:10]
##3.获取批量操作的范围,应该是个向量
genelist <- colnames(data)
##4.开始for循环,批量执行单次操作
gene <- "FOXA1"
genedata <- as.numeric(data[,gene])
for(i in 1:length(genelist)){
## 1.指示
print(i)
## 2.计算
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,变成lapply + 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)
}
### 测试函数功能
mycor("GATA3")
### 第2步lapply批量作用于函数,返回list
system.time(lapplylist <- lapply(genelist,mycor))
### 第3步do.call 转换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
### 依然是lapply 三步走,只有一点点不一样
library(future.apply)
plan(multisession) #先告诉它你有多少线程 在任务管理器中查看
message("outside>>how many cores can use now: ", nbrOfWorkers()) #查看可用线程数
### 第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)
}
### 测试函数功能
mycor("GATA3")
### 第2步lapply批量作用于函数,返回list
### system.time(lapplylist <- lapply(genelist,mycor))
system.time(lapplylist <- future_lapply(genelist,mycor))#唯一的差别
### 第3步do.call 转换list
cor_data <- do.call(rbind,lapplylist)
#################################################################
### 别急,future_lapply的优势在后面介绍
3.一些注意事项
写for循环的时候用数字去代表元素要更方便,因为数字不但可以代表元素,还可以表示下标;而直接用for (i in colnames(data)) 这样的语句,i代表的是一个个基因名,在后续的填写结果中多有不便。
for循环需要添加容器,即一个空的dataframe,lapply不需要
使用lapply时,请先完成对一个数据的function处理,再把其整合到lapply的多对象操作中。操之过急只会延缓进度
lapply处理后用do.call合并/或者直接用sapply。详见上一篇内容