写在开头

最近基于肝细胞癌微血管侵袭单细胞分析研究在整理文章中的图表复现:

Figure1中其他的图都比较简单,之前已经整理过类似的了,所以就重复啦。

图1E及F使用Dimplot函数中的split.by参数进行调整之后,再设置对应的颜色可视化即可。

图1G也是细胞比例的堆叠柱状图,不过倒是可以试试看除了堆叠柱状图外还有什么好看的展示方法。

这期准备复现一下附图的Figure1B

supplementary Figure1B简析

左图:按样本分组的 tSNE(Tumor vs Adjacent Non-Tumor)

  • 每个点表示一个样本(如 T1, NT1),代表一个组织来源(肿瘤或癌旁组织)。
  • 点的位置是该样本中所有细胞在 tSNE 空间的平均坐标。
  • 颜色区分了样本类型(Tumor vs Adjacent non-tumor)。
  • 分离清晰说明这两种组织在转录层面存在显著差异。

右图:按患者分组的 tSNE(MVI+ vs MVI−)

  • 每个点表示一个患者,基于该患者所有细胞的 tSNE 平均坐标。
  • 颜色区分了 MVI 状态(有微血管侵犯 vs 无微血管侵犯)。
  • MVI+ 患者(P1–P3)较为集中,而 MVI− 患者(P4–P5)远离他们,说明 MVI 状态与细胞表达特征相关。

文章提供代码简析

######## Supplementary 1B
library(Seurat)
library(dplyr)
library(ggpubr)

scdata3 = ScaleData(scdata3,features = rownames(scdata3))
scdata3 = RunPCA(scdata3, features = rownames(scdata3)) 
scdata3 = RunTSNE(scdata3,features = rownames(scdata3))   


tsne = data.frame(row.names = as.character(unique(scdata3$Patient)))
for (i in as.character(unique(scdata3$Patient))) {
  
  a = scdata3@reductions$tsne@cell.embeddings[rownames(filter([email protected],Patient == i)),1:2]
  tsne[i,'tsne1'] = mean(a[,1] %>% as.numeric())
  tsne[i,'tsne2'] = mean(a[,2] %>% as.numeric())

}

tsne2 = data.frame(row.names = as.character(unique(scdata3$orig.ident)))
for (i in as.character(unique(scdata3$orig.ident))) {
  
  a = scdata3@reductions$tsne@cell.embeddings[rownames(filter([email protected],orig.ident == i)),1:2]
  tsne2[i,'tsne1'] = mean(a[,1] %>% as.numeric())
  tsne2[i,'tsne2'] = mean(a[,2] %>% as.numeric())
}


tsne2$tissue = "N"
tsne2[rownames(pca2) %in% c("T1","T2","T3","T4","T5"), "tissue"] = "Tumor"

tsne$MVI = "MVI"
tsne[rownames(tsne) %in% c("P4",'P5'), "MVI"] = "No MVI"

ggplot(data=tsne,aes(x= tsne1,y= tsne2))+geom_point(shape=21,size= 6,aes(color=factor(MVI)shape =factor(MVI) ) )

ggplot(data= tsne2,aes(x= tsne1,y= tsne2))+geom_point(shape=21,size= 6,aes(color=factor(tissue)shape =factor(tissue) ) )

直接基于给的代码,使用ggplot直接可视化得到的结果和文章结果差异较大,所以按照文章的附图调整了下代码

结果数据整理

###加载包和数据----
rm(list=ls())
options(stringsAsFactors = F) 
source('scRNA_scripts/lib.R')

load("sce.all.Rdata")
sce.all.int = readRDS('2-harmony/sce.all_int.rds')

#添加需要的MVI分组信息
sce.all$MVI_status <- ifelse(sce.all$patient %in% c("patient1""patient2""patient3"), 
                             "MVI+"
                             "MVI-")

[email protected] = sce.all

sel.clust = "celltype"
sce.all.int <- SetIdent(sce.all.int, value = sel.clust)
table([email protected]

#运行tsne得到结果----
sce.all.int = RunTSNE(sce.all.int,dims = 1:15, 
                  reduction = "harmony")

计算平均坐标及可视化

首先计算t-SNE坐标,然后创建两个数据框tsnetsne2,最后绘制两个ggplot图对象p1p2,并将它们组合在一起。

tsne = data.frame(row.names = as.character(unique(sce.all.int$patient)))
for (i in as.character(unique(sce.all.int$patient))) {
  
  a = sce.all.int@reductions$tsne@cell.embeddings[rownames(filter([email protected],patient == i)),1:2]
  tsne[i,'tsne1'] = mean(a[,1] %>% as.numeric())
  tsne[i,'tsne2'] = mean(a[,2] %>% as.numeric())
  
}
tSNE坐标图初步探索分组变量

tsne2 = data.frame(row.names = as.character(unique(sce.all.int$group)))
for (i in as.character(unique(sce.all.int$group))) {
  
  a = sce.all.int@reductions$tsne@cell.embeddings[rownames(filter([email protected],group == i)),1:2]
  tsne2[i,'tsne1'] = mean(a[,1] %>% as.numeric())
  tsne2[i,'tsne2'] = mean(a[,2] %>% as.numeric())
}


tsne2$tissue = "Non tumor"
tsne2[rownames(tsne2) %in% c("1T","2T","3T","4T","5T"), "tissue"] = "Tumor"

tsne$MVI = "MVI+ Patient"
tsne[rownames(tsne) %in% c("Patient4",'Patient5'), "MVI"] = "MVI- Patient"
  1. 创建tsne数据框
  • 初始化一个空的数据框tsne,行名设置为患者的唯一标识符。
  • 对于每个患者,计算其在t-SNE空间中的平均坐标(tsne1tsne2),并将这些坐标存储在tsne数据框中。
  • 将所有样本的tissue设置为“Non tumor”。
  • 将特定样本组(1T到5T)的tissue设置为“Tumor”
  1. 创建tsne2数据框
  • 初始化一个空的数据框tsne2,行名设置为样本组的唯一标识符。
  • 对于每个样本组,计算其在t-SNE空间中的平均坐标(tsne1tsne2),并将这些坐标存储在tsne2数据框中。
  • 将所有患者的MVI设置为“MVI+ Patient”。
  • 将特定患者(Patient4和Patient5)的MVI设置为“MVI- Patient”。

绘制ggplot图

#可视化

library(ggplot2)

p2 <- ggplot(data = tsne, aes(x = tsne1, y = tsne2, color = factor(MVI), label = rownames(tsne))) +
  geom_point(size = 6) +  # 实心圆
  geom_text(vjust = -1, size = 5, color = "black") +  # 添加标签
  scale_color_manual(
    values = c("MVI+ Patient" = "#E65C35""MVI- Patient" = "#3AA5A7"),
    labels = c("MVI" = "MVI+ Patient""No MVI" = "MVI- Patient")
  ) +
  xlim(-10, 10) +
  ylim(-10, 10) +
  theme_minimal(base_size = 14) +
  theme(
    panel.border = element_rect(colour = "black", fill = NA, size = 1),
    panel.grid = element_blank(),
    axis.title = element_text(size = 14),
    axis.text = element_text(size = 12),
    legend.title = element_blank(),
    legend.position = "bottom"
  ) +
  labs(
    title = "tSNE plot (Patient)",
    x = "tSNE 1",
    y = "tSNE 2"
  )

library(ggplot2)

p1 <- ggplot(data = tsne2, aes(x = tsne1, y = tsne2, color = factor(tissue),label = rownames(tsne2))) +
  geom_point(size = 6) +  # 实心圆
  geom_text(aes(label = tissue), vjust = -1, size = 5, color = "black") +  # 添加标签
  scale_color_manual(
    values = c("Tumor" = "#db8a8a""Non tumor" = "#8c83a4"),
    labels = c("T" = "Tumor""N" = "Non tumor")
  ) +
  xlim(-20, 20) +
  ylim(-10, 15) +
  theme_minimal(base_size = 14) +
  theme(
    panel.border = element_rect(colour = "black", fill = NA, size = 1),
    panel.grid = element_blank(),
    axis.title = element_text(size = 14),
    axis.text = element_text(size = 12),
    legend.title = element_blank(),
    legend.position = "bottom"
  ) +
  labs(
    title = "tSNE plot (Sample)",
    x = "tSNE 1",
    y = "tSNE 2"
  )

p1+p2

  1. 绘制患者t-SNE图(p2
  • 使用ggplot函数,指定数据源为tsne,x轴和y轴分别为tsne1tsne2,颜色和形状根据MVI分类。
  • 添加实心圆点和文本标签,标签内容为行名。
  • 设置颜色比例尺,图例标签,坐标轴限制,主题和标签。
  1. 绘制样本t-SNE图(p1
  • 使用ggplot函数,指定数据源为tsne2,x轴和y轴分别为tsne1tsne2,颜色和形状根据tissue分类。
  • 添加实心圆点和文本标签,标签内容为tissue
  • 设置颜色比例尺,图例标签,坐标轴限制,主题和标签。

复现不足之处

  1. 在可视化sample分组的时候,label标签无法指定为group分群,推测可能是因为group分群中是以数字开头
  1. 使用的实心圆大小没有文章中大,所以结果看起来比较紧凑

文末友情宣传

如果你也想做单细胞转录组数据分析,最好是有自己的计算机资源哦,比如我们的满足你生信分析计算需求的低价解决方案,而且还需要有基本的生物信息学基础,也可以看看我们的生物信息学马拉松授课,你的生物信息学入门课。

2025年也会继续学习分享单细胞内容,并且组建了交流群——承包你2025全部的单细胞转录组降维聚类分群,欢迎一起讨论交流学习!