生信喵 发表于 2025-11-30 08:23:21

免疫细胞网络图

<h1>背景</h1>
<p>复现原文免疫细胞之间相关性的网络图</p>
<p><img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/11/30/mikylgsykk8o780gc8r.png" alt="" /></p>
<p>出自PMID: 30842092文章</p>
<p>节点的颜色代表细胞所属的cluster,节点的大小代表生存分析的log_rank_p,用圆心点的颜色展示HR,连线颜色代表正/负相关,连线的粗细代表相关性Pvalue。</p>
<h1>应用场景</h1>
<p>用网络图同时展示相关关系、pvalue、聚类/分类结果、跟预后的关系。</p>
<ul>
<li>例如例文中各细胞之间的相关关系、跟预后的关系</li>
<li>或表达谱数据中多个基因的相关性、聚类结果、pvalue、跟预后的关系,更丰富。</li>
</ul>
<p><strong>画法说明:</strong></p>
<ul>
<li>用代码画出例图中除圆心以外的部分。</li>
<li>再根据“output_HR_corlor.csv”的最后一列,用Illustrator在圆心上画点,点的颜色代表HR的正负。</li>
<li>最后输出的pdf文件是矢量图,可以用Illustrator等软件调整细胞名等文字的位置。</li>
</ul>
<h1>环境设置</h1>
<pre><code class="language-{r}">library(reshape2)
library(corrplot)
library(plyr)
library(igraph) #用于绘制网络图

Sys.setenv(LANGUAGE = &quot;en&quot;) #显示英文报错信息
options(stringsAsFactors = FALSE) #禁止chr转成factor
</code></pre>
<h2>参数设置</h2>
<pre><code class="language-{r}">poscol &lt;- &quot;#FB9A99&quot; #正相关用红色连线
negcol &lt;- &quot;#C6DBEF&quot; #负相关用蓝色连线

mycol &lt;- c(&quot;#FDBF6F&quot;, &quot;#1F78B4&quot;, &quot;#E31A1C&quot;, &quot;#8C510A&quot;) #cluster的颜色,如果有更多类,就给更多的颜色
</code></pre>
<h1>输入文件</h1>
<p>至少要提供easy_input_immune.csv文件,例如免疫细胞矩阵,或基因表达矩阵(把这里的免疫细胞替换成基因即可)。如果没有生存分析结果,可以用其他pvalue代替。</p>
<p>easy_input_immune.csv,免疫细胞矩阵文件,用于计算相关系数和P值、把细胞分成4个cluster、通过卡相关性的P值来建立细胞间的连接关系。每行一个sample,每列一种细胞。最后一列fibioblast用mcpcounter获得;文中其他22种免疫细胞用CIBERSORT计算获得,还可以用ssGSEA来量化免疫细胞。</p>
<p>easy_input_HR.csv,生存分析结果,需要HR(节点圆心点的颜色,用AI来加)和p value(节点圆的大小)列。</p>
<pre><code class="language-{r}"># 免疫细胞矩阵
input_data &lt;- read.csv(&quot;easy_input_immune.csv&quot;, row.names = 1, check.names = F)
dim(input_data)
input_data

# 生存分析结果
bb &lt;- read.csv(&quot;easy_input_HR.csv&quot;,header = T);
head(bb)
bb$Cell.types &lt;- as.character(bb$Cell.types)
colnames(bb) &lt;- c(&quot;ID&quot;)
#用pvalue控制节点圆的大小
bb$weight &lt;- abs(log10(bb$log_rank_p))
#用HR标圆心点的颜色
bb$weight_HR &lt;- (as.numeric(bb$HR)-1)*100
bb$colr &lt;- ifelse(bb$weight_HR&lt;0, &quot;green&quot;, &quot;black&quot;)
head(bb)

#保存到文件,根据最后一列颜色在最后输出的pdf文件中画圆心
write.csv(bb, &quot;output_HR_corlor.csv&quot;, quote = F)
</code></pre>
<h1>相关性的计算</h1>
<h2>计算每两种细胞间的相关性</h2>
<p>计算每两种细胞间的相关性cor,用corrplot可视化,看看聚成几类比较好。</p>
<pre><code class="language-{r,"># options(scipen = 100,digits = 4)
corr &lt;- cor(input_data, method = &quot;spearman&quot;)
corrplot(corr,title = &quot;&quot;,
         method = &quot;pie&quot;, #或&quot;circle&quot; (default), &quot;square&quot;, &quot;ellipse&quot;, &quot;number&quot;, &quot;pie&quot;, &quot;shade&quot; and &quot;color&quot;
         outline = T, addgrid.col = &quot;darkgray&quot;,
         order=&quot;hclust&quot;, addrect = 4, #hclust聚为4类,根据数据的具体情况调整
         mar = c(4,0,4,0), #撑大画布,让细胞名显示完全
         rect.col = &quot;black&quot;, rect.lwd = 5, cl.pos = &quot;b&quot;,
         tl.col = &quot;black&quot;, tl.cex = 1.08, cl.cex = 1.5, tl.srt=60)
</code></pre>
<p><img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/11/30/mikywrh6ybwhc4eg9n.png" alt="" /></p>
<h2>计算相关性分析的P值</h2>
<p>也可以用Hmsic包来求,但是发现它输出的P值有限制。</p>
<pre><code class="language-{r,">cor.mtest &lt;- function(corr, ...) {
corr &lt;- as.matrix(corr)
n &lt;- ncol(corr)
p.corr &lt;- matrix(NA, n, n)
diag(p.corr) &lt;- 0
for (i in 1:(n - 1)) {
    for (j in (i + 1):n) {
      tmp &lt;- cor.test(corr[, i],method = &quot;spearman&quot;, corr[, j], ...)
      p.corr &lt;- p.corr &lt;- tmp$p.value
    }
}
colnames(p.corr) &lt;- rownames(p.corr) &lt;- colnames(corr)
p.corr
}

p.corr &lt;- cor.mtest(input_data)
head(p.corr[, 1:5])
</code></pre>
<h2>计算节点间的连接关系</h2>
<p>只保留那些相关性较强的连接</p>
<pre><code class="language-{r}">#合并相关系数和P值
rr &lt;- as.data.frame(corr);
rr$ID &lt;- rownames(rr)
cor &lt;- melt(rr,&quot;ID&quot;,value.name = &quot;cor&quot;); #head(cor)

pp &lt;- as.data.frame(p.corr);
pp$ID &lt;- rownames(pp)
pvalue &lt;- melt(pp,&quot;ID&quot;,value.name = &quot;pvalue&quot;); #head(pvalue)
colnames(pvalue) &lt;- c(&quot;from&quot;,&quot;to&quot;,&quot;pvalue&quot;)

corpvlue &lt;- cbind(pvalue, cor)
head(corpvlue)
corpvlue &lt;- corpvlue[, -c(4:5)]
head(corpvlue)
dim(corpvlue)

#去掉相关性较弱的连接
corpvlue &lt;- corpvlue #只保留pvalue &lt; 0.0001的
dim(corpvlue)
corpvlue$weight &lt;- corpvlue$pvalue
corpvlue$weight &lt;- -log10(corpvlue$weight)
head(corpvlue)

#去掉相关系数为1,也就是两个相同变量之间的连接
corpvlue &lt;- corpvlue[!corpvlue$cor==1,]
dim(corpvlue)
#去掉相关系数一样的连接--也就是重复计算的连接
summary(duplicated(corpvlue$weight))
corpvlue &lt;- corpvlue[!duplicated(corpvlue$weight),]
dim(corpvlue)

#相关系数的正负用不同颜色表示
corpvlue$color &lt;- ifelse(corpvlue$cor&lt;0, negcol, poscol)

#保存到文件,便于查看
write.csv(corpvlue, &quot;output_links.csv&quot;)
</code></pre>

生信喵 发表于 2025-11-30 08:23:48

<h1>利用矩阵文件进行细胞的聚类</h1>
<p>细胞聚类的结果综合考虑了&quot;hclust&quot;的结果、&quot;kmeans&quot;聚类的结果、以及目前的研究现状</p>
<pre><code class="language-{r}">cellcluster &lt;- as.data.frame(t(input_data))
#cellcluster

hc &lt;- hclust(dist((cellcluster)))
hcd &lt;- as.dendrogram(hc)
(clus4 &lt;- cutree(hc, 4)) #分4类

A &lt;- as.character(rownames(as.data.frame(subset(clus4,clus4==1))))
B &lt;- as.character(rownames(as.data.frame(subset(clus4,clus4==2))))
C &lt;- as.character(rownames(as.data.frame(subset(clus4,clus4==3))))
D &lt;- as.character(rownames(as.data.frame(subset(clus4,clus4==4))))
cls &lt;- list(A,B,C,D)

nodes &lt;- as.data.frame(unlist(cls))
nodes$type &lt;- c(rep(&quot;B&quot;,9),rep(&quot;A&quot;,4),rep(&quot;C&quot;,5),rep(&quot;D&quot;,5))
names(nodes) &lt;- c(&quot;media&quot;,&quot;type.label&quot;)

#以hclust的结果为基础,调整部分细胞所属的cluster
nodes$type.label &lt;- &quot;B&quot;
nodes$type.label &lt;- &quot;A&quot;
nodes$type.label &lt;- &quot;A&quot;
nodes$type.label &lt;- &quot;A&quot;
nodes$type.label &lt;- &quot;C&quot;
nodes$type.label &lt;- &quot;C&quot;
nodes$type.label &lt;- &quot;A&quot;

nodes &lt;- as.data.frame(nodes)
nodes$media &lt;- as.character(nodes$media)
nodes
</code></pre>
<h1>构建网络的input文件</h1>
<pre><code class="language-{r}"># 合并生存分析的数据和细胞分类的数据
summary(nodes$media %in% bb$ID) #检查细胞名是否一致
nodes &lt;- merge(nodes, bb, by.x = &quot;media&quot;, &quot;ID&quot;, all.x = T, all.y = T) #按细胞名merge

nodes$Fraction &lt;- abs(nodes$weight_HR)
nodes$id &lt;- paste(&quot;S&quot;, 01:23, sep = &quot;&quot;)
nodes &lt;- nodes
nodes &lt;- nodes[,c(ncol(nodes),1:ncol(nodes)-1)]
nodes &lt;- nodes
nodes

#建立nodes和links的连接id,把细胞名换成ID
paste0(&quot;'&quot;,nodes$media,&quot;'&quot;,&quot;=&quot;,&quot;'&quot;,nodes$id,&quot;'&quot;,collapse = &quot;,&quot;)
corpvlue$from &lt;- revalue(corpvlue$from,c('B cells memory'='S1','B cells naive'='S2','Dendritic cells activated'='S3',
                                       'Dendritic cells resting'='S4','Eosinophils'='S5','Fibroblasts'='S6','Macrophages M0'='S7',
                                       'Macrophages M1'='S8','Macrophages M2'='S9','Mast cells activated'='S10',
                                       'Mast cells resting'='S11','Monocytes'='S12','Neutrophils'='S13',
                                       'NK cells activated'='S14','NK cells resting'='S15','Plasma cells'='S16',
                                       'T cells CD4 memory activated'='S17','T cells CD4 memory resting'='S18',
                                       'T cells CD4 naive'='S19','T cells CD8'='S20','T cells follicular helper'='S21',
                                       'T cells gamma delta'='S22','T cells regulatory Tregs'='S23'))
corpvlue$to &lt;- revalue(corpvlue$to,c('B cells memory'='S1','B cells naive'='S2','Dendritic cells activated'='S3',
                                 'Dendritic cells resting'='S4','Eosinophils'='S5','Fibroblasts'='S6','Macrophages M0'='S7',
                                 'Macrophages M1'='S8','Macrophages M2'='S9','Mast cells activated'='S10',
                                 'Mast cells resting'='S11','Monocytes'='S12','Neutrophils'='S13',
                                 'NK cells activated'='S14','NK cells resting'='S15','Plasma cells'='S16',
                                 'T cells CD4 memory activated'='S17','T cells CD4 memory resting'='S18',
                                 'T cells CD4 naive'='S19','T cells CD8'='S20','T cells follicular helper'='S21',
                                 'T cells gamma delta'='S22','T cells regulatory Tregs'='S23'))
(links &lt;- corpvlue)

#利用nodes和links构建网络的input文件
net &lt;- graph_from_data_frame(d=links, vertices=nodes, directed=T)
</code></pre>
<h2>开始画图</h2>
<pre><code class="language-{r,"># Generate colors based on cell clusters:
V(net)$color &lt;- revalue(nodes$type.label,c(&quot;A&quot;=mycol,&quot;B&quot;=mycol,&quot;C&quot;=mycol,&quot;D&quot;=mycol))
# Compute node degrees (#links) and use that to set node size:
# Set edge width based on weight-log10(p_value):
V(net)$size &lt;- (1 + V(net)$weight)*3 #节点圆的大小,可根据自己的数据再做调整
V(net)$label &lt;- V(net)$media #设置标签
E(net)$arrow.mode &lt;- 0 #不需要箭头
E(net)$edge.color &lt;- &quot;tomato&quot; # tomato gray80
E(net)$width &lt;- 1+E(net)$weight/6#连接之间权重

pdf(&quot;Immune_network.pdf&quot;, width = 9.75, height = 8.78 )
plot(net,
   layout=layout_in_circle, #按圆圈布局
   edge.curved=.2, #画弯曲的连线
   vertex.label.color=V(net)$color, #细胞名的颜色
   vertex.label.dist= -2, #标签和节点的位置错开,后期还是要用AI调整
   edge.color=links$color)

#cluster的图例
legend(&quot;topright&quot;, #图例的位置
       c(&quot;Cell cluster-A&quot;, &quot;Cell cluster-B&quot;, &quot;Cell cluster-C&quot;, &quot;Cell cluster-D&quot;),
       pch=21, col=&quot;black&quot;, pt.bg=mycol, pt.cex=3,
       cex=1.3, bty=&quot;n&quot;, ncol=1)

#节点圆大小的图例,参考了FigureYa75base_volcano
f &lt;- c(0.05, 0.001, 0.00001, 0.00000001)
s &lt;- sqrt(abs(log10(f)))*3
legend(&quot;bottomright&quot;,
       inset=c(0,-.1), #向下移
       legend=f, text.width = .2,
       title = &quot;logrank test, P value&quot;, title.adj = -.5,
       pch=21, pt.cex=s, bty='n',
       horiz = TRUE, #横向排列
       col = &quot;black&quot;)

#连线的图例
legend(&quot;bottomright&quot;,
       c(&quot;Positive correlation with P &lt; 0.0001&quot;,
         &quot;Negative correlation with P &lt; 0.0001&quot;),
       col = c(poscol, negcol), bty=&quot;n&quot;,
       cex = 1, lty = 1, lwd = 5)

dev.off()
</code></pre>
<p><img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/11/30/mikz6u4zfyfaoa9hp8c.png" alt="" /></p>
<p>文字的位置用Illustrator调整;再根据“output_HR_corlor.csv”的最后一列用Illustrator在圆心上画点,点的颜色代表HR的正负。</p>

生信喵 发表于 2025-11-30 08:25:04

<p>文中所用数据可以关注公众号“生信喵实验柴”<br />
<img src="https://tcapi.voiceclouds.cn:8444/uploads/2025/09/07/mf9nu72s90ofyseu9hl.png" alt="" /><br />
发送关键词“20250509”获取</p>
页: [1]
查看完整版本: 免疫细胞网络图