
在R语言中有个强大的R包ggplot2,它能够帮助我们完成很多绘图工作,方便又好用。Python环境中用于绘图可能会比较常用mamatplotlib,seaborn,plotly以及ggplot(Python),本次就用mamatplotlib和seaborn来进行横向和比例条形图的绘制。
R语言版本的横向和比例条形图也在既往的推文中出现过:https://mp.weixin.qq.com/s/nuFHE4AyUMsBvbGbEhDxBg
# 可以选择延续scanpy中创建的环境也就是sc
# 激活环境
conda activate sc# 服务器就自己登陆
# 自己的电脑就去终端上输入
jupyter lab加载库(顺手都加载了),其实绘制柱状图的核心是matplotlib.pyplot和pandas库
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import scanpy as sc
import numpy as np
import anndata as ad
import pooch
import os# 确定位置,自己修改
os.getcwd()# 路径要结合实际情况
adata = sc.read_h5ad('~/scRNA_V5.h5ad')adata.obs
检查一下“老演员”。
sc.pl.umap(
adata, # AnnData 对象
color="celltype", # 按 celltype 分组上色
size=0.8, # 点大小,类似 pt.size
legend_loc='right margin', # 在图上显示标签,等价于 label = TRUE
ncols=2, # 控制子图排列列数
title=None, # 可选:不显示默认标题
show =False
)
提取数据
# 统计celltype数量
dat = adata.obs["celltype"].value_counts().reset_index()
dat.columns = ['Celltypes', 'Cell_num']
dat
# 使用pd.Categorical进行排序并增加label列
dat['Celltypes'] = pd.Categorical(dat['Celltypes'],
categories=['CD4+ T-cells',
"Fibroblasts",
"B-cells",
"CD8+ T-cells",
"Neutrophils",
"Monocytes",
"Adipocytes",
"NK cells",
"Endothelial cells"], # 可以对每个细胞进行排序,也可以直接写celltype
ordered=True)
# dat.rename(columens={old_index1: new_index1, old_index2: new_index2}, inplace=True) 还有这种直接映射的
dat["label"] = dat["Celltypes"].astype(str)+":"+ dat["Cell_num"].astype(str)
dat
# 自定义颜色(使用tab20调色板)
mycolors = sns.color_palette('tab20', len(dat))
# 创建图形(调整尺寸适应纵向图)
plt.figure(figsize=(10, 6)) # 宽度>高度更适合纵向图
# 绘制纵向柱状图(交换x/y轴即可)
barplot = sns.barplot(
data=dat,
x='Celltypes', # 现在x轴是类别
y='Cell_num', # y轴是数值
palette=mycolors
)
# 在每个柱子上方显示细胞数
for i, value in enumerate(dat['Cell_num']):
barplot.text(
x=i, # x坐标对应柱子索引
y=value + 0.01 * max(dat['Cell_num']), # y坐标在柱子顶部稍上方
s=str(value), # 显示细胞数值
ha='center', # 水平居中
va='bottom', # 垂直底部对齐
fontsize=10
)
# 美化样式
plt.xticks(
rotation=45, # 旋转45度防止文字重叠
ha='right', # 旋转后右对齐更美观
fontsize=12
)
plt.xlabel('') # 隐藏x轴标签
plt.ylabel('Cell Number', fontsize=12) # 显示y轴标签
plt.title("Cell Type Distribution", pad=20) # 添加标题(pad增加间距)
# 调整布局并保存
plt.tight_layout()
plt.savefig('vertical_cell_num.pdf', bbox_inches='tight', dpi=300)
plt.show()
其实横向和纵向的变化关键在于sns.barplot中的x,y中输入了什么数据。
# 自定义颜色(可以根据R里mycolors换成想用的颜色)
mycolors = sns.color_palette('tab20', len(dat)) # len函数可以返回多少行数
# 画横向柱状图
plt.figure(figsize=(7, 8))
barplot = sns.barplot(
data=dat, # 用的数据来源是DataFrame dat
y='Celltypes', # y轴对应的列是 dat 中的 'Celltypes',作为分类变量(类别标签)
x='Cell_num', # x轴对应的列是 dat 中的 'Cell_num',作为数值大小(柱子长度)
palette=mycolors # 使用自定义颜色列表 mycolors 给不同的类别上色
)
# 在条形左侧显示标签
for i, (value, label) in enumerate(zip(dat['Cell_num'], dat['label'])):
barplot.text(
x=0, # 文字的横坐标位置,放在x=0,也就是条形的起点位置
y=i, # 文字的纵坐标位置,对应第i个条形(条形在y轴的第i个位置)
s=label, # 要显示的文字内容,来自dat['label'],比如 "Bcell:50"
va='center', # 文字垂直方向居中对齐
ha='left', # 文字水平方向左对齐
fontsize=12, # 文字大小
color='black' # 文字颜色
)
# 美化样式
plt.xlabel('')
plt.ylabel('')
plt.title("Celltypes")
plt.xticks(rotation=45, fontsize=10, color='black')
plt.yticks([])
plt.tight_layout()
plt.savefig('column_cell_num.pdf',bbox_inches='tight',dpi=300)
plt.show()
这里可以用大模型对里面的一句代码进行解释:for i, (value, label) in enumerate(zip(dat['Cell_num'], dat['label']))
# 假设数据如下
dat = {
'Cell_num': [1007, 762, 667],
'label': ['CD4+ T-cells', 'Fibroblasts', 'B-cells']
}
# zip 后的效果
list(zip(dat['Cell_num'], dat['label']))
# 结果:
# [(1007, 'CD4+ T-cells'),
# (762, 'Fibroblasts'),
# (667, 'B-cells')]# enumerate 添加索引后
list(enumerate(zip(dat['Cell_num'], dat['label'])))
# 结果:
# [
# (0, (1007, 'CD4+ T-cells')),
# (1, (762, 'Fibroblasts')),
# (2, (667, 'B-cells'))
# ]也就是通过zip和enumerate的组合拳形式构建了每个细胞的细胞数和需要展示的文字内容。
# 想把所有样本和细胞类型相同的归为一组,groupby(["orig.ident", "celltype"]):按照 orig.ident 和 celltype 两列对细胞进行分组。
# size每个分组的 总行数(无论有没有 NaN),而conut每个分组中 每一列的非 NaN 数量
count_df = adata.obs.groupby(["orig.ident","celltype"]).size().reset_index(name = "count")
# 计算比例 lambda x: x / x.sum() * 100,计算当前组内各项的百分比
count_df["Proportion"] = count_df.groupby(["orig.ident"])["count"].transform(lambda x:x/x.sum()*100)
# 长数据改成宽数据格式
pivot_df = count_df.pivot(index="orig.ident", columns="celltype", values="Proportion").fillna(0)
pivot_df.to_csv("pivot_df.csv")
pivot_df
# 自定义颜色,替换为你自己的颜色字典,key是celltype名称
mycolors = {
'CD4+ T-cells':"#326795",
"Fibroblasts":"#aec0db",
"B-cells":"#da7a31",
"CD8+ T-cells":"#e9b581",
"Neutrophils":"#318736",
"Monocytes":"#94ce8c",
"Adipocytes": "#b63b3a",
"NK cells":"#ef9d9a",
"Endothelial cells":"#8a66a7",
}
# 开始画图
plt.figure(figsize=(7, 8)) # 单位为英寸
bottom = pd.Series([0] * len(pivot_df), index=pivot_df.index)
x = pivot_df.index # 样本名,x轴坐标
for celltype, color in mycolors.items():
if celltype in pivot_df.columns:
plt.bar(x, pivot_df[celltype],
bottom=bottom,
label=celltype,
color=color,
alpha=0.9)
bottom += pivot_df[celltype]
plt.title('Celltype Proportion per types', fontsize=14)
plt.xlabel('Types', fontsize=12)
plt.ylabel('Proportion (%)', fontsize=12)
plt.xticks(rotation=45, ha='right', fontsize=10)
plt.yticks(fontsize=10)
plt.legend(title='Celltypes', bbox_to_anchor=(1.05, 1), loc='upper left', fontsize=10)
plt.tight_layout()
plt.savefig("stacked_bar_celltypes_vertical.pdf", dpi=300, bbox_inches='tight')
plt.show()
注:若对内容有疑惑或者有发现明确错误的朋友,请联系后台(欢迎交流)。更多相关内容可关注公众号:生信方舟 。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。