You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Seaborn或其他工具制作Graphpad Prism风格带全数据点小提琴图

复刻Graphpad Prism风格的小提琴图(Python/R实现)

Python方案(优先Seaborn)

要实现Prism那种「仅在数据密集区水平分散点、尾部点保留中心线」的效果,核心思路是根据数据密度动态调整点的水平偏移:密度高的区域偏移大(避免重叠),密度低的尾部偏移为0。

步骤与代码示例

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import gaussian_kde

# 加载示例数据
tips = sns.load_dataset("tips")

# 初始化画布
fig, ax = plt.subplots(figsize=(8, 6))

# 绘制基础小提琴图
sns.violinplot(data=tips, x="day", y="total_bill", ax=ax, inner=None, color="lightgray")

# 自定义点的位置:按密度调整水平偏移
for idx, day in enumerate(tips["day"].unique()):
    # 获取当前类别的数据
    data = tips[tips["day"] == day]["total_bill"].values
    # 计算核密度估计(KDE)
    kde = gaussian_kde(data)
    density = kde(data)
    # 归一化密度值,用于生成偏移
    norm_density = (density - density.min()) / (density.max() - density.min())
    # 设置偏移范围:密度最高的点偏移±0.2,尾部点偏移0
    offset = norm_density * np.random.uniform(-0.2, 0.2, size=len(data))
    # 绘制带偏移的点
    ax.scatter(np.full(len(data), idx) + offset, data, s=20, alpha=0.6, color="#3377bb")

# 调整坐标轴与样式
ax.set_xlabel("Day")
ax.set_ylabel("Total Bill")
plt.tight_layout()
plt.show()

关键细节

  • 用gaussian_kde计算数据密度,确保偏移只发生在数据密集区
  • 可通过调整np.random.uniform的范围(比如±0.15)控制偏移幅度,避免过度分散
  • 如果需要更精准的对称偏移,可替换随机偏移为基于密度的对称分布值

替代工具:plotnine(仿ggplot2)

若习惯ggplot语法,plotnine结合自定义位置调整函数也能实现:

from plotnine import ggplot, aes, geom_violin, geom_point, scale_x_discrete
from plotnine.data import tips
import numpy as np
from scipy.stats import gaussian_kde

# 自定义位置调整:仅在高密度区抖动
def position_prism_jitter(width=0.2):
    def adjust(data):
        kde = gaussian_kde(data['y'])
        density = kde(data['y'])
        norm_density = (density - density.min())/(density.max()-density.min())
        data['x'] += norm_density * np.random.uniform(-width, width, len(data))
        return data
    return adjust

(ggplot(tips, aes(x='day', y='total_bill'))
 + geom_violin(fill='lightgray', inner=None)
 + geom_point(position=position_prism_jitter(width=0.2), alpha=0.6, color='#3377bb')
 + scale_x_discrete()
).draw()

R方案(ggplot2)

R中用ggplot2可通过自定义位置函数或扩展包实现类似效果:

自定义偏移实现

library(ggplot2)
library(dplyr)
library(KernSmooth)

# 加载示例数据
data(tips)

# 自定义位置调整函数
position_prism <- function(width = 0.2) {
  function(data) {
    # 按分组计算密度并生成偏移
    data <- data %>%
      group_by(x) %>%
      mutate(
        density = bkde(y, kernel = "normal")$y[findInterval(y, bkde(y)$x)],
        norm_density = (density - min(density))/(max(density) - min(density)),
        x = x + norm_density * runif(n(), -width, width)
      ) %>%
      ungroup()
    data
  }
}

# 绘制图形
ggplot(tips, aes(x = day, y = total_bill)) +
  geom_violin(fill = "lightgray", inner = NULL) +
  geom_point(position = position_prism(width = 0.2), alpha = 0.6, color = "#3377bb") +
  labs(x = "Day", y = "Total Bill") +
  theme_minimal()

简化方案:ggbeeswarm扩展包

若不需要严格复刻尾部无偏移,ggbeeswarm的position_quasirandom会自动根据密度调整点位置,效果接近Prism:

library(ggbeeswarm)

ggplot(tips, aes(x = day, y = total_bill)) +
  geom_violin(fill = "lightgray", inner = NULL) +
  geom_quasirandom(width = 0.2, alpha = 0.6, color = "#3377bb") +
  labs(x = "Day", y = "Total Bill")

内容的提问来源于stack exchange,提问作者Dan K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 16:11:10