suppressMessages({ library(plyr) # 数据处理工具包 library(CellChat) # 单细胞通讯分析核心包 library(patchwork) # 图形组合工具 library(Seurat) # 单细胞数据分析基础包 library(SingleCellExperiment) # 单细胞数据结构包 library(ggalluvial) # 桑基图绘制工具 library(repr) # 图形尺寸调整工具 library(ggplot2) # 基础可视化包 library(gplots) # 热图绘制(heatmap.2函数) library(RColorBrewer) # 颜色 palette 生成 library(tidyr) # 数据重塑(长表/宽表转换) library(stringr) # 字符串处理 library(ComplexHeatmap)# 复杂热图绘制})options(stringsAsFactors = FALSE)'%!in%' <- function(x,y)!('%in%'(x,y))# 定义数据输出路径path_data="/cellchat/output_files/"# 加载预处理后的CellChat对象(分别对应肥胖、瘦、减重三种状态)# 数据已过滤:排除淋巴B细胞,仅保留特定细胞类型,经过严格子采样obese=readRDS(paste0(path_data,"cellchat_obese_no_lymphatic_bcells_kit_scott_only_ct_fine_stringent_subsampled.rds"))lean=readRDS(paste0(path_data,"cellchat_lean_no_lymphatic_bcells_kit_scott_only_ct_fine_stringent_subsampled.rds"))wl=readRDS(paste0(path_data,"cellchat_weightloss_no_lymphatic_bcells_kit_scott_only_ct_fine_stringent_subsampled.rds"))# 减重组(wl)缺少Mu5细胞集群,需与肥胖组保持细胞类型一致(通过liftCellChat函数对齐)group.new = levels(obese@idents) # 以肥胖组的细胞类型为参考wl <- liftCellChat(wl, group.new) # 对齐减重组细胞类型lean <- liftCellChat(lean, group.new) # 对齐瘦组细胞类型# 合并不同状态的CellChat对象(用于组间比较)object.list <- list(Obese = obese, Lean = lean)obese_lean <- mergeCellChat(object.list, add.names = names(object.list)) # 肥胖vs瘦object.list <- list(Obese = obese, Weightloss = wl)obese_wl <- mergeCellChat(object.list, add.names = names(object.list)) # 肥胖vs减重object.list <- list(Obese = obese, Lean = lean, Weightloss = wl)cellchat_all <- mergeCellChat(object.list, add.names = names(object.list)) # 三者合并# 计算各状态下细胞通讯网络的中心性指标(基于推断的通讯网络netP)# 中心性指标反映细胞在通讯中的"角色"(如发送者、接收者等)obese <- netAnalysis_computeCentrality(obese, slot.name = "netP")lean <- netAnalysis_computeCentrality(lean, slot.name = "netP")wl <- netAnalysis_computeCentrality(wl, slot.name = "netP")# --------------------------# 提取并整理中心性指标数据# --------------------------# 获取所有组中出现的通讯通路(避免通路遗漏)pathways.show.all <- unique(c(obese@netP$pathways,wl@netP$pathways,lean@netP$pathways))# 定义中心性指标及其对应中文含义(用于结果标注)measure = c("outdeg","indeg","flowbet","info") # 算法层面的指标名称measure.name = c("Sender","Receiver","Mediator","Influencer") # 生物学解读名称# 提取肥胖组的中心性数据并标准化mat2=NULL # 临时存储数据框for(j in pathways.show.all){ centr=obese@netP$centr[j] for(i in 1:length(centr)) { centr0 <- centr[[i]] if(!is.null(centr0)){ mat <- matrix(unlist(centr0), ncol = length(centr0), byrow = FALSE) mat <- t(mat) rownames(mat) <- names(centr0); colnames(mat) <- names(centr0$outdeg)
if (!is.null(measure)) { mat <- mat[measure,] if (!is.null(measure.name)) { rownames(mat) <- measure.name } } mat <- sweep(mat, 1L, apply(mat, 1, max), '/', check.margin = FALSE) mat=as.data.frame(mat) mat$Pathway=j mat$Role=rownames(mat)
if (is.null(mat2)){ mat2=data.frame(mat) } else { mat2=rbind(mat2,mat) } } }}mat2$Condition="Obese" mat_obese=mat2 mat2=NULLfor(j in pathways.show.all){ centr=lean@netP$centr[j] for(i in 1:length(centr)) { centr0 <- centr[[i]] if(!is.null(centr0)){ mat <- matrix(unlist(centr0), ncol = length(centr0), byrow = FALSE) mat <- t(mat) rownames(mat) <- names(centr0); colnames(mat) <- names(centr0$outdeg) if (!is.null(measure)) { mat <- mat[measure,] if (!is.null(measure.name)) { rownames(mat) <- measure.name } } mat <- sweep(mat, 1L, apply(mat, 1, max), '/', check.margin = FALSE) mat=as.data.frame(mat) mat$Pathway=j mat$Role=rownames(mat) if (is.null(mat2)){ mat2=data.frame(mat) } else { mat2=rbind(mat2,mat) } } }}mat2$Condition="Lean"mat_lean=mat2mat2=NULLfor(j in pathways.show.all){ centr=wl@netP$centr[j] for(i in 1:length(centr)) { centr0 <- centr[[i]] if(!is.null(centr0)){ mat <- matrix(unlist(centr0), ncol = length(centr0), byrow = FALSE) mat <- t(mat) rownames(mat) <- names(centr0); colnames(mat) <- names(centr0$outdeg) if (!is.null(measure)) { mat <- mat[measure,] if (!is.null(measure.name)) { rownames(mat) <- measure.name } } mat <- sweep(mat, 1L, apply(mat, 1, max), '/', check.margin = FALSE) mat=as.data.frame(mat) mat$Pathway=j mat$Role=rownames(mat) if (is.null(mat2)){ mat2=data.frame(mat) } else { mat2=rbind(mat2,mat) } } }}mat2$Condition="Weightloss"mat_wl=mat2mat_final=rbind(mat_obese,mat_lean,mat_wl)head(mat_final) write.csv(mat_final, paste0(path_data,"cellchat_ct_fine_no_lymphatic_bcells_kit_stringent_subsampled_scott_only_centrality_all.csv"), row.names=FALSE)df.net <- subsetCommunication(obese)unique(df.net$pathway_name) write.csv(df.net, paste0(path_data,"cellchat_ct_fine_no_lymphatic_bcells_kit_stringent_subsampled_scott_only_net_obese.csv"), row.names=FALSE)df.net <- subsetCommunication(lean)write.csv(df.net, paste0(path_data,"cellchat_ct_fine_no_lymphatic_bcells_kit_stringent_subsampled_scott_only_net_lean.csv"), row.names=FALSE)df.net <- subsetCommunication(wl)write.csv(df.net, paste0(path_data,"cellchat_ct_fine_no_lymphatic_bcells_kit_stringent_subsampled_scott_only_net_wl.csv"), row.names=FALSE)options(repr.plot.width = 6, repr.plot.height = 6) heatmap.df <- list(contrib = data.frame(matrix(ncol = 0, nrow = 0)), pval = data.frame(matrix(ncol = 0, nrow = 0)))cellchat=cellchat_all genotypes <- names(cellchat@net) for (i in c(2:3)){ gg <- rankNet(cellchat, mode = "comparison", comparison=c(1,i) , title= genotypes[i] , cutoff.pvalue = 0.05 # 初步筛选P值阈值 , stacked = T, show.raw = T, do.stat = TRUE, return.data = FALSE)
temp <- data.frame( gg$data[gg$data$group == levels(gg$data$group)[1],c("contribution", "pvalues")], # 处理组的贡献度和P值 control.contribution=gg$data[gg$data$group == levels(gg$data$group)[2],c("contribution")], # 对照组的贡献度 row.names = rownames(gg$data)[gg$data$group == levels(gg$data$group)[2]] # 行名设为通路 )
temp2 <- data.frame((temp[,1]/temp[,3]), row.names = rownames(temp)) colnames(temp2) <- genotypes[i]
if(sum(dim(heatmap.df$contrib) == c(0,0))){ heatmap.df$contrib <- temp2 } else{ heatmap.df$contrib <- merge(heatmap.df$contrib, temp2, all = TRUE, by = "row.names") rownames(heatmap.df$contrib) <- heatmap.df$contrib$Row.names heatmap.df$contrib <- heatmap.df$contrib[,c(-1)] }
temp2 <- data.frame(p.adjust(temp[,2], method="bonferroni"), row.names = rownames(temp)) colnames(temp2) <- genotypes[i]
if(sum(dim(heatmap.df$pval) == c(0,0))){ heatmap.df$pval <- temp2 } else { heatmap.df$pval <- merge(heatmap.df$pval, temp2, all = TRUE, by = "row.names") rownames(heatmap.df$pval) <- heatmap.df$pval$Row.names heatmap.df$pval <- heatmap.df$pval[,c(-1)] }}heatmap.df$contrib <- log2(heatmap.df$contrib)heatmap.df$pval <- data.frame(sapply(heatmap.df$pval, as.numeric), row.names=rownames(heatmap.df$pval))heatmap.df$contrib <- data.frame(sapply(heatmap.df$contrib, as.numeric), row.names=rownames(heatmap.df$contrib))temp <- heatmap.df$contribtemp$Pathway <- rownames(temp)heatmap.df.contrib.wide <- gather(temp, Group, log2FC_contrib, Lean:Weightloss, factor_key=TRUE)print(dim(heatmap.df.contrib.wide))head(heatmap.df.contrib.wide)temp <- heatmap.df$pvaltemp$Pathway <- rownames(temp)heatmap.df.pval.wide <- gather(temp, Group, adjusted_pval,Lean:Weightloss, factor_key=TRUE)print(dim(heatmap.df.pval.wide))head(heatmap.df.pval.wide)heatmap.df.wide <- merge(heatmap.df.contrib.wide, heatmap.df.pval.wide, by=c("Pathway","Group"), all.x = TRUE, all.y = TRUE)head(heatmap.df.wide)heatmap.df.wide[which(heatmap.df.wide$Pathway=="NRG"),]MAX.CONTRIB <- max(abs(heatmap.df$contrib[!(sapply(heatmap.df$contrib, is.infinite) | is.na(heatmap.df$contrib))]))MAX.CONTRIB <- round(MAX.CONTRIB) INF.VALUE <- MAX.CONTRIB+1 heatmap.df.wide$adjusted_pval[heatmap.df.wide$log2FC_contrib<0.2]=1heatmap.df.wide$adjusted_pval[heatmap.df.wide$log2FC_contrib<0.2]=1 options(repr.plot.width = 20, repr.plot.height = 5) heatmap.df2 <- heatmap.dfheatmap.df2$contrib[sapply(heatmap.df2$contrib, is.infinite) & heatmap.df2$contrib > 0] <- INF.VALUEheatmap.df2$contrib[sapply(heatmap.df2$contrib, is.infinite) & heatmap.df2$contrib < 0] <- -INF.VALUEheatmap.df2$pval[(abs(heatmap.df2$contrib) < 0.2)] <- 1heatmap.df2$pval[is.na(heatmap.df2$pval)] <- 2heatmap.df2$pval <- heatmap.df2$pval[(apply(is.na(heatmap.df2$contrib), 1, sum) < 2),]heatmap.df2$contrib <- heatmap.df2$contrib[(apply(is.na(heatmap.df2$contrib), 1, sum) < 2),]
heatmap.df2$contrib <- heatmap.df2$contrib[(apply(heatmap.df2$pval > 0.01, 1, sum) < 2),]heatmap.df2$pval <- heatmap.df2$pval[(apply(heatmap.df2$pval > 0.01, 1, sum) < 2),]
heatmap.df2$pval[heatmap.df2$pval == 2] <- NA
heatmap.df2$sig <- heatmap.df2$pvalheatmap.df2$sig[] <- ''heatmap.df2$sig[heatmap.df2$pval <= 0.01] <- '*'
heatmap.df2$sig[is.na(heatmap.df2$pval)] <- '-'
heatmap.df2$contrib[is.na(heatmap.df2$contrib)] <- 0
heatmap.df2$sig <- heatmap.df2$sig[,c("Lean","Weightloss")]heatmap.df2$pval <- heatmap.df2$pval[,c("Lean","Weightloss")]heatmap.df2$contrib <- heatmap.df2$contrib[,c("Lean","Weightloss")]
scale.interval.size <- 0.05num_breaks <- (MAX.CONTRIB * 2 / scale.interval.size)+1breaks <- c(-(INF.VALUE+1), seq(from=-MAX.CONTRIB, to=MAX.CONTRIB, length.out=num_breaks), INF.VALUE+1)midpoint <- 0
rampCol2 <- colorRampPalette(c("#6699FF", "white", "#FF6600"))(length(breaks)-1)mypalette <- c(rampCol2)mypalette[1] <- "#5689EF" mypalette[num_breaks+1] <- "#EF5600"
heatmap.df3 <- heatmap.df2heatmap.df4 <- heatmap.df2
heatmap.df3$contrib <- heatmap.df2$contrib[(apply(heatmap.df2$contrib > 0 & heatmap.df2$sig != '', 1, sum) >=2 & apply(heatmap.df2$contrib < 0 & heatmap.df2$sig != '', 1, sum) == 0) |(apply(heatmap.df2$contrib < 0 & heatmap.df2$sig != '', 1, sum) >=2 & apply(heatmap.df2$contrib > 0 & heatmap.df2$sig != '', 1, sum) == 0) ,]heatmap.df3$sig <- heatmap.df2$sig[(apply(heatmap.df2$contrib > 0 & heatmap.df2$sig != '', 1, sum) >=2 & apply(heatmap.df2$contrib < 0 & heatmap.df2$sig != '', 1, sum) == 0) |(apply(heatmap.df2$contrib < 0 & heatmap.df2$sig != '', 1, sum) >=2 & apply(heatmap.df2$contrib > 0 & heatmap.df2$sig != '', 1, sum) == 0) ,]heatmap.df3$sig <- heatmap.df3$sig[order(apply(heatmap.df3$contrib, 1, mean)),]heatmap.df3$contrib <- heatmap.df3$contrib[order(apply(heatmap.df3$contrib, 1, mean)),]
heatmap.df4$contrib <- heatmap.df2$contrib[!((apply(heatmap.df2$contrib > 0 & heatmap.df2$sig != '', 1, sum) >=2 & apply(heatmap.df2$contrib < 0 & heatmap.df2$sig != '', 1, sum) == 0) |(apply(heatmap.df2$contrib < 0 & heatmap.df2$sig != '', 1, sum) >=2 & apply(heatmap.df2$contrib > 0 & heatmap.df2$sig != '', 1, sum) == 0)) ,]heatmap.df4$sig <- heatmap.df2$sig[!((apply(heatmap.df2$contrib > 0 & heatmap.df2$sig != '', 1, sum) >=2 & apply(heatmap.df2$contrib < 0 & heatmap.df2$sig != '', 1, sum) == 0) |(apply(heatmap.df2$contrib < 0 & heatmap.df2$sig != '', 1, sum) >=2 & apply(heatmap.df2$contrib > 0 & heatmap.df2$sig != '', 1, sum) == 0)) ,]
heatmap.df4$contrib <- heatmap.df4$contrib[with(data.frame(heatmap.df4$sig == '*'), order(-Lean,-Weightloss)),]heatmap.df4$sig <- heatmap.df4$sig[with(data.frame(heatmap.df4$sig == '*'), order(-Lean,-Weightloss)),]
heatmap.df4$change <- heatmap.df4$contribheatmap.df4$change[] <- 0heatmap.df4$change[heatmap.df4$contrib > 0 & heatmap.df4$sig != ''] <- 1heatmap.df4$change[heatmap.df4$contrib < 0 & heatmap.df4$sig != ''] <- -1heatmap.df4$sig <- heatmap.df4$sig[order(apply(heatmap.df4$change, 1, sum), decreasing = TRUE),]heatmap.df4$contrib <- heatmap.df4$contrib[order(apply(heatmap.df4$change, 1, sum), decreasing = TRUE),]
heatmap.df4$contrib <- heatmap.df4$contrib[order(apply(heatmap.df4$sig == '*', 1, sum)),]heatmap.df4$sig <- heatmap.df4$sig[order(apply(heatmap.df4$sig == '*', 1, sum)),]
heatmap.2(t(heatmap.df3$contrib) , col=mypalette , Rowv=NULL , Colv=NULL , dendrogram="none" , na.rm = TRUE , breaks=breaks, density.info="none", trace="none" , symm=F,symkey=F,symbreaks=T, scale="none" , margins = c(33,35) , lhei=c(1,5), lwid=c(1,7) , cellnote = t(heatmap.df3$sig) ,notecex=3.0 ,notecol="black" ,cexRow=3 ,cexCol=1.5 )
heatmap.2(t(heatmap.df4$contrib) , col=mypalette , Rowv=NULL , Colv=NULL , dendrogram="none" , na.rm = TRUE , breaks=breaks, density.info="none", trace="none" , symm=F,symkey=F,symbreaks=T, scale="none" , margins = c(33,35) , lhei=c(1,5), lwid=c(1,7) , cellnote = t(heatmap.df4$sig) ,notecex=3.0 ,notecol="black" ,cexRow=3 ,cexCol=1.5 )
lean=heatmap.final.corr$pval[,"Lean",drop=FALSE]colnames(lean)=c("pval")lean$contrib=heatmap.final.corr$contrib$Leanlean$Condition="Lean"lean$Group=rownames(lean)rownames(lean)=NULL
head(lean)
wl=heatmap.final.corr$pval[,"Weightloss",drop=FALSE]colnames(wl)=c("pval")wl$contrib=heatmap.final.corr$contrib$Weightlosswl$Condition="Weightloss"wl$Group=rownames(wl)rownames(wl)=NULL
head(wl)
merged.df=rbind(lean,wl)
merged.df[c('Pathway', 'Pair')] <- str_split_fixed(merged.df$Group, '__', 2)
merged.df[c('Sender', 'Receiver')] <- str_split_fixed(merged.df$Pair, '\\|', 2)
rownames(merged.df)=NULL
head(merged.df)
write.csv(merged.df,paste0(path_data,"rankNet_vs_obese_ct_fine_pairwise_scott_only_subsampled_stringent_no_lymphatic_bcells_kit.csv"))