如何基于Pandas DataFrame绘制Shell Plot(壳图)?
问题描述
我有一个记录配体-受体对相互作用数量的DataFrame,数据如下:
import pandas as pd d = {'ligand': ['B cells','CAFs','Malignant cells','T cells','TAMs','TAMs','TAMs','TAMs','TAMs','TAMs','TAMs','TECs','unclassified'], 'receptor': ['TAMs','TAMs','TAMs','TAMs','B cells','CAFs','Malignant cells','T cells','TAMs','TECs','unclassified','TAMs','TAMs'], 'interactions': [18, 29, 89, 22, 17, 12, 48, 34, 56, 27, 14, 53, 24]} df = pd.DataFrame(d)
我需要将其可视化为Shell Plot(壳图),样式为内外双圈结构,通过连线粗细表示相互作用数量,但找不到相关实现资料,请问如何用Python模块实现?
实现方案
方法1:使用pycirclize库(推荐)
pycirclize是专门用于环形可视化的Python库,能快速实现壳图效果,无需复杂的坐标计算。
步骤1:安装依赖库
pip install pycirclize
步骤2:编写实现代码
import pandas as pd from pycirclize import Circos # 加载数据 d = {'ligand': ['B cells','CAFs','Malignant cells','T cells','TAMs','TAMs','TAMs','TAMs','TAMs','TAMs','TAMs','TECs','unclassified'], 'receptor': ['TAMs','TAMs','TAMs','TAMs','B cells','CAFs','Malignant cells','T cells','TAMs','TECs','unclassified','TAMs','TAMs'], 'interactions': [18, 29, 89, 22, 17, 12, 48, 34, 56, 27, 14, 53, 24]} df = pd.DataFrame(d) # 获取所有唯一细胞类型,作为环形节点 cell_types = sorted(list(set(df["ligand"].tolist() + df["receptor"].tolist()))) n_cells = len(cell_types) cell_to_idx = {cell: idx for idx, cell in enumerate(cell_types)} # 创建Circos对象,设置环形间距 circos = Circos(n_sectors=n_cells, space=5) circos.text("配体-受体相互作用", size=12, loc=(100, 0)) # 配置内外圈:外圈为配体,内圈为受体 for sector in circos.sectors: cell_name = cell_types[sector.idx] # 外圈添加细胞类型标签 sector.text(cell_name, size=10, orientation="vertical") # 内圈绘制灰色背景弧 sector.arc(inner_radius=80, outer_radius=90, color="#e0e0e0") # 绘制相互作用连线,线宽与作用数量成正比 max_interaction = df["interactions"].max() for _, row in df.iterrows(): ligand_idx = cell_to_idx[row["ligand"]] receptor_idx = cell_to_idx[row["receptor"]] line_width = (row["interactions"] / max_interaction) * 5 # 连接内外圈对应节点 circos.link( circos.sectors[ligand_idx], 0.5, circos.sectors[receptor_idx], 0.5, color="#4a90e2", alpha=0.7, linewidth=line_width, ) # 保存并显示图像 circos.savefig("ligand_receptor_shell_plot.png", dpi=300) circos.show()
方法2:使用matplotlib手动绘制
如果不想额外安装库,可通过matplotlib结合numpy手动实现基础壳图:
import pandas as pd import matplotlib.pyplot as plt import numpy as np # 加载数据 d = {'ligand': ['B cells','CAFs','Malignant cells','T cells','TAMs','TAMs','TAMs','TAMs','TAMs','TAMs','TAMs','TECs','unclassified'], 'receptor': ['TAMs','TAMs','TAMs','TAMs','B cells','CAFs','Malignant cells','T cells','TAMs','TECs','unclassified','TAMs','TAMs'], 'interactions': [18, 29, 89, 22, 17, 12, 48, 34, 56, 27, 14, 53, 24]} df = pd.DataFrame(d) # 获取所有唯一细胞类型并映射为角度 cell_types = sorted(list(set(df["ligand"].tolist() + df["receptor"].tolist()))) n_cells = len(cell_types) cell_to_angle = {cell: 2 * np.pi * idx / n_cells for idx, cell in enumerate(cell_types)} # 创建极坐标画布 fig, ax = plt.subplots(figsize=(8, 8), subplot_kw={'projection': 'polar'}) ax.set_theta_zero_location("N") ax.set_theta_direction(-1) ax.set_xticks([cell_to_angle[cell] for cell in cell_types]) ax.set_xticklabels(cell_types, fontsize=10) ax.set_ylim(0, 2) ax.set_yticks([]) # 绘制内外圈轮廓 outer_radius = 2 inner_radius = 1.5 ax.plot(np.linspace(0, 2*np.pi, 100), [outer_radius]*100, color="#333333") ax.plot(np.linspace(0, 2*np.pi, 100), [inner_radius]*100, color="#333333") # 绘制相互作用连线 max_interaction = df["interactions"].max() for _, row in df.iterrows(): ligand_angle = cell_to_angle[row["ligand"]] receptor_angle = cell_to_angle[row["receptor"]] line_width = (row["interactions"] / max_interaction) * 3 # 绘制配体(外圈)到受体(内圈)的连线 ax.plot([ligand_angle, receptor_angle], [outer_radius, inner_radius], color="#4a90e2", alpha=0.7, linewidth=line_width) plt.title("配体-受体相互作用", y=1.1, fontsize=12) plt.savefig("ligand_receptor_shell_plot_matplotlib.png", dpi=300) plt.show()
内容的提问来源于stack exchange,提问作者Yulia Kentieva
相关产品推荐
相关产品推荐

