Scissor:联合表型数据,Bulk-seq和scRNA的分析软件

前言

作者开发Scissor的目的是结合bulk-seq的数据,寻找与某一性状显著相关的单细胞亚群,然后从表型的角度解释这些细胞亚群的生物学意义。作者开发Scissor的动机是由于目前对细胞亚群的分群大多基于scRNA的表达量进行无监督聚类,却鲜有人从表型的角度解释这些单细胞亚群。作者认为,相同的细胞亚群可能会导致相同表型的发生

附上文献地址:《Identifying phenotype-associated subpopulations by integrating bulk and single-cell sequencing data》

完整流程

# 加载数据
## 单细胞数据
location <- "https://xialab.s3-us-west-2.amazonaws.com/Duanchen/Scissor_data/"
load(url(paste0(location, 'scRNA-seq.RData')))
## bulk-seq data
load(url(paste0(location, 'TCGA_LUAD_exp1.RData')))
## 表型 data
load(url(paste0(location, 'TCGA_LUAD_survival.RData')))

# 预处理单细胞数据
sc_dataset <- Seurat_preprocessing(sc_dataset, verbose = F)

# 预处理表型数据
phenotype <- bulk_survival[,2:3]
colnames(phenotype) <- c("time", "status")

# 运行Scissor
infos1 <- Scissor(bulk_dataset, sc_dataset, phenotype, alpha = 0.05, 
                 family = "cox", Save_file = 'Scissor_LUAD_survival.RData')


Scissor_select <- rep(0, ncol(sc_dataset))
names(Scissor_select) <- colnames(sc_dataset)
## infos1$Scissor_pos代表 β > 0 的细胞
## infos1$Scissor_neg代表 β < 0 的细胞
Scissor_select[infos1$Scissor_pos] <- 1
Scissor_select[infos1$Scissor_neg] <- 2
sc_dataset <- AddMetaData(sc_dataset, metadata = Scissor_select, col.name = "scissor")
DimPlot(sc_dataset, reduction = 'umap', group.by = 'scissor', cols = c('grey','indianred1','royalblue'), pt.size = 1.2, order = c(2,1))


如上图,每一个点代表一个细胞,红色代表与表型呈正相关的细胞;蓝色代表与表型呈负相关的细胞
因此,经过计算获得的回归系数β表征每一个细胞与表型的相关程度,若回归系数β > 0代表该细胞与某种表型呈现正相关;若回归系数β < 0代表该细胞与某种表型呈现负相关

原理


如上图所示,作者需要的 input 文件有三种,单细胞数据,表型数据(可以说分类表型数据,也可以是连续型表型数据)和bulk-seq的表达矩阵


第一步,软件利用分位数回归去除了bulk-seq和scRNA的批次效应;第二步基于单细胞数据构建cell与cell间的similarity network(G);第三步计算单细胞表达矩阵对bulk-seq表达矩阵的皮尔斯相关系数,记作S={sij}n×m,n为sample的总数目,m为细胞的总数目;第四步,利用相关性矩阵S作为决策变量,表型数据作为响应变量建立回归关系,设回归系数为β,在计算β的过程中将以及cell与cell间的similarity network(G)的部分信息(利用度矩阵和邻接矩阵构建拉普拉斯矩阵)作为估计的正则项

那么接下来的任务就是估计出回归系数β,转换为最优化问题:
β等于

其中:

  1. L(拉普拉斯矩阵) = I - D-1/2AD-1/2
  2. 上式的A={aij}m×m代表cell与cell间的similarity network(G)的邻接矩阵(aij介于0—1之间)
  3. 上式的D={dij}m×m是G的度矩阵,dij=∑j=1aij,其中 j = 1—m
  4. λ 为 penalty

其中:

  1. 表示sample i 对每一个细胞的皮尔斯相关系数,si2表示sample i 与第2个细胞的皮尔斯相关系数
  2. 若表型数据Y是连续型变量
    l(β)定义为:

    3.若表型数据Y是分类型变量
    l(β)定义为:

那么计算出来的回归系数为β越高代表某细胞亚群与某表型的相关性比较高,反之比较低

事实上bulk-seq的sample数量与表型数据的数量是一致的。而决策变量Si表征每个细胞与sample i的相关性,相关性高即代表该细胞与该sample的表达模式相同,也就是sample i 中这个细胞的含量较多(该细胞含量多才会使得该细胞与该sample之间表达模式相同),因此可以等量代换为某个细胞的含量与表型之间的关系,因此β值为正且越大,则说明该细胞含量对表型影响呈正相关且影响大。反之β为负且越小,则说明该细胞含量对表型影响呈正负相关且影响大

代码

第一部分:

# single cell
location <- "https://xialab.s3-us-west-2.amazonaws.com/Duanchen/Scissor_data/"
load(url(paste0(location, 'scRNA-seq.RData')))
sc_dataset <- Seurat_preprocessing(sc_dataset, verbose = F)

# bulk seq
load(url(paste0(location, 'TCGA_LUAD_exp1.RData')))
load(url(paste0(location, 'TCGA_LUAD_survival.RData')))

# 提取表型数据
all(colnames(bulk_dataset) == bulk_survival$TCGA_patient_barcode)
phenotype <- bulk_survival[,2:3]
colnames(phenotype) <- c("time", "status")

其中bulk-seq的列表示不同sample,行表示不同基因;表型数据:

phenotype

第二部分:

# 读取数据
bulk_dataset = bulk_dataset
sc_dataset = sc_dataset
phenotype = phenotype
tag = NULL
alpha = 0.05
cutoff = 0.2
family = "cox"
Save_file = "Scissor_inputs.RData"
Load_file = NULL

# 单细胞基因和bulk-seq基因取交集
common <- intersect(rownames(bulk_dataset), rownames(sc_dataset))

# 构建cell与cell间的similarity network(G)
sc_exprs <- as.matrix(sc_dataset@assays$RNA@data)
network  <- as.matrix(sc_dataset@graphs$RNA_snn)
diag(network) <- 0
network[which(network != 0)] <- 1

# Dataset before quantile normalization.
dataset0 <- cbind(bulk_dataset[common,], sc_exprs[common,])        
# Dataset after  quantile normalization.
dataset1 <- normalize.quantiles(dataset0)                           
rownames(dataset1) <- rownames(dataset0)
colnames(dataset1) <- colnames(dataset0)

# 得到单细胞表达矩阵和bulk-seq表达矩阵
Expression_bulk <- dataset1[,1:ncol(bulk_dataset)]
Expression_cell <- dataset1[,(ncol(bulk_dataset) + 1):ncol(dataset1)]
# 单细胞矩阵和bulk-seq表达量矩阵求皮尔斯相关系数所构成的相关系数矩阵,作为决策变量
X <- cor(Expression_bulk, Expression_cell)
quality_check <- quantile(X)

# 定义表型的响应变量
Y <- as.matrix(phenotype)

# 计算回归系数β
set.seed(123)
# 初次计算
fit0 <- APML1(X, Y, family = family, penalty = "Net", alpha = alpha[i], Omega = network, nlambda = 100, nfolds = 10)
# 再次计算,将fit0$lambda.min作为新模型的 lambda
fit1 <- APML1(X, Y, family = family, penalty = "Net", alpha = alpha[i], Omega = network, lambda = fit0$lambda.min)
# 获取回归系数β
Coefs <- as.numeric(fit1$Beta)
Cell1 <- colnames(X)[which(Coefs > 0)]
Cell2 <- colnames(X)[which(Coefs < 0)]
percentage <- (length(Cell1) + length(Cell2)) / ncol(X)

因此,经过计算获得的回归系数β表征每一个细胞与表型的相关程度,若回归系数β > 0代表该细胞与某种表型呈现正相关;若回归系数β < 0代表该细胞与某种表型呈现负相关

细胞水平评估

此外,作者还提供了一个估计细胞水平的函数evaluate.cell(),其核心代码如下:

Scissor_result = infos1

selected_cell <- c(Scissor_result$Scissor_pos, Scissor_result$Scissor_neg)

# Expression_bulk意义参见第二部分代码
m <- ncol(Expression_bulk)
# selected_cell意义参见第二部分代码
n <- length(selected_cell)
evaluate_summary <- as.data.frame(matrix(0, n, 11, dimnames = list(selected_cell,
                        c("Mean correlation","Correlation > 0","Correlation < 0","Significant Correlation","Coefficient",
                          "Beta 0%","Beta 25%","Beta 50%","Beta 75%","Beta 100%","Probability of zero"))))

   

cor_test_p <- matrix(0, m, n)
for (i in 1:m){
     Sys.sleep(1 / 100)
     for (j in 1:n){
          #相关性的显著性检验
          cor_test_p[i,j] <- cor.test(Expression_bulk[,i], Expression_cell[,selected_cell[j]])$p.value
    }
}
    
cor_test_FDR <- matrix(p.adjust(as.numeric(cor_test_p), method = "fdr"), m)
for (j in 1:n){
     # X代表单细胞矩阵和bulk-seq表达量矩阵求皮尔斯相关系数所构成的相关系数矩阵,参考第二部分
      evaluate_summary[j,1] <- mean(X[,selected_cell[j]])
      evaluate_summary[j,2] <- percent(sum(X[,selected_cell[j]] > 0)/m)
      evaluate_summary[j,3] <- percent(sum(X[,selected_cell[j]] < 0)/m)
      evaluate_summary[j,4] <- percent(sum(cor_test_FDR[,j] < FDR_cutoff)/m)
}

其中:X代表单细胞矩阵和bulk-seq表达量矩阵求皮尔斯相关系数所构成的相关系数矩阵



因此结果的第一列表示的是某一个细胞与所有bulk-seq样本相关性的均值;第二列是统计X矩阵相关系数大于0的比例;第三列是统计X矩阵相关系数小于0的比例

小tips:关于APML1函数

cox为参数作为例子

# 读取数据
x=X
y=Y
Omega = network
alpha = alpha[i]
lambda=NULL
nlambda = 100
rlambda=NULL
nfolds = 10
foldid=NULL
inzero=TRUE
wbeta=rep(1,ncol(x))
sgn=rep(1,ncol(x))
isd=FALSE
iysd=FALSE
keep.beta=FALSE
ifast=TRUE
thresh=1e-7
maxit=1e+5
penalty="Net"
wbeta=abs(wbeta)
family = 'cox'

fit=CoxL0(x,y,Omega,alpha,lambda,nlambda,rlambda,nfolds,foldid,inzero,wbeta,sgn,isd,keep.beta,ifast,thresh,maxit)

class(fit)="APML1"
# 最终返回 fit
return(fit)

其中CoxL0函数的功能是估计β的算式,是用C++写的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容