Scanpy可视化技巧--UMAP图优化

前几天后台有同学私信说想要美化下scanpy绘制的UMAP图,给了篇单细胞文章中的UMAP截图,我们写了一个函数,用于美化scanpy的UMAP图,思路还是比较简单,基本上全部是由deeepseek帮忙实现,能让你的UMAP图拥有:

✓ 细胞亚群轮廓线
✓ 智能标签定位
✓ 科研风坐标轴
✓ 自适应比例标注

核心美化功能解析

功能1:核密度轮廓线

复制代码
kde = KernelDensity(bandwidth=0.5)kde.fit(coordinates)plt.contour(xx, yy, Z, levels=[peak*0.1]) 
  • 原理:通过核密度估计寻找细胞聚集区

  • 优势:比 convex hull 更贴合真实分布

功能2:智能标签

复制代码
ax.text(x, y, cell_type, bbox=dict(facecolor='white', alpha=0.9))
  • 自动计算亚群中位数坐标

  • 白色半透明背景增强对比度

  • 圆角边框提升美观度

功能3:科研风坐标轴​​​​​​​

复制代码
ax.arrow(x_min, y_min, dx, 0)  # X轴箭头ax.text(x_center, y_min-offset, 'UMAP1')  # 动态标签
  • 自动计算箭头长度比例

  • 自适应图像长宽比

  • 标签防遮挡设计

完整函数封装​​​​​​​

复制代码
import numpy as npimport pandas as pdimport scanpy as scimport matplotlib.pyplot as pltfrom sklearn.neighbors import KernelDensity

def enhance_umap(adata, color='celltype', figsize=(6,6)):    fig, ax = plt.subplots(figsize=figsize)    sc.pl.umap(        adata,        color=color,        legend_loc=None,        frameon=False,        size=15,        ax=ax,        add_outline=True,        show=False    )
    for cell_type in adata.obs[color].unique():        # 获取对应细胞类型的UMAP坐标        mask = adata.obs[color] == cell_type        x = adata.obsm["X_umap"][mask, 0]        y = adata.obsm["X_umap"][mask, 1]
        x_min, x_max = x.min() - 0.5, x.max() + 0.5        y_min, y_max = y.min() - 0.5, y.max() + 0.5        xx, yy = np.mgrid[x_min:x_max:100j, y_min:y_max:100j]
        xy_train = np.vstack([x, y]).T        xy_test = np.vstack([xx.ravel(), yy.ravel()]).T
        # 核密度估计        kde = KernelDensity(bandwidth=0.5, metric='euclidean')        kde.fit(xy_train)
        # 密度        Z = np.exp(kde.score_samples(xy_test))        Z = Z.reshape(xx.shape)
        # 绘制轮廓        plt.contour(            xx, yy, Z,             levels=[Z.max() * 0.1],             colors='gray',             linestyles='--',              linewidths=1.2,              alpha=0.75         )
    cell_type_counts = adata.obs[color].value_counts(normalize=True) * 100    for cell_type, percentage in cell_type_counts.items():        mask = adata.obs[color] == cell_type        x = np.median(adata.obsm["X_umap"][mask, 0])        y = np.median(adata.obsm["X_umap"][mask, 1])        ax.text(            # x, y, f"{cell_type} ({percentage:.1f}%)",            x, y, f"{cell_type}",            fontsize=10,             ha="center",             color="black",            bbox=dict(                facecolor='white',         # 添加白色背景                edgecolor='none',                 alpha=0.65,                boxstyle="round,pad=0.4"   # 添加圆角            )          )    ax = plt.gca()    ax.set_xlabel('UMAP1', fontsize=10)    ax.set_ylabel('UMAP2', fontsize=10)    # 获取坐标轴数据范围    x_min, x_max = ax.get_xlim()    y_min, y_max = ax.get_ylim()    # 动态计算箭头参数(基于数据范围和图像比例)    x_range = x_max - x_min    y_range = y_max - y_min    aspect_ratio = (fig.get_size_inches()[0] / fig.get_size_inches()[1]) * (y_range / x_range)  # 校正宽高比    # 箭头长度(数据范围的10%)    dx = x_range * 0.1 * aspect_ratio    dy = y_range * 0.1 * aspect_ratio  # 根据实际显示比例调整Y轴长度    # 箭头头部参数(与箭头长度成比例)    head_width = dy * 0.1    head_length = dx * 0.1    # 绘制X轴箭头    ax.arrow(        x_min, y_min,        dx, 0,        head_width=head_width,        head_length=head_length,        fc='black',        ec='black'    )    # 绘制Y轴箭头    ax.arrow(        x_min, y_min,        0, dy,        head_width=head_width,        head_length=head_length,        fc='black',        ec='black'    )    # 计算标签位置(箭头中点+微调偏移)    label_offset = dx * 0.15  # 偏移量为箭头长度的15%    ax.text(        x_min + dx/2,         y_min - label_offset,  # 向下偏移        'UMAP1',        ha='center',         va='top',         fontsize=10    )    ax.text(        x_min - label_offset,         y_min + dy/2,        'UMAP2',        rotation=90,        ha='right',         va='center',        fontsize=10    )
相关推荐
Miu(数分版)1 小时前
PowerBi中REMOVEFILTERS怎么使用?
数据分析·产品运营·powerbi
lilye661 小时前
精益数据分析(18/126):权衡数据运用,精准把握创业方向
数据挖掘·数据分析
Leo.yuan1 小时前
数据仓库是什么?数据仓库架构有哪些?
大数据·数据库·数据仓库·架构·数据分析
Aloudata技术团队6 小时前
Aloudata Agent :基于 NoETL 明细语义层的分析决策智能体
数据库·数据分析·数据可视化
随缘而动,随遇而安7 小时前
第五十二篇 浅谈ETL系统设计
大数据·数据仓库·数据分析·数据库开发·数据库架构
杨超越luckly8 小时前
HTML应用指南:利用GET请求获取微博签到位置信息
大数据·信息可视化·数据分析·html·html5
云天徽上17 小时前
【数据可视化-21】水质安全数据可视化:探索化学物质与水质安全的关联
安全·机器学习·信息可视化·数据挖掘·数据分析
谁家有个大人17 小时前
Python数据清洗笔记(上)
开发语言·笔记·python·数据分析
Jayen H19 小时前
数据分析:用Excel做周报
数据挖掘·数据分析