如何在Seaborn kdeplot中实现单密度图的0界分色填充
实现单密度图的左右分色填充(Seaborn + Matplotlib)
问题描述
我用Polars生成了包含treat_B字段的模拟数据,想要用Seaborn的kdeplot绘制该字段的单密度图,要求将0值左侧的填充区域设为红色,右侧设为蓝色。但添加hue="direction"参数后会生成两个独立的密度曲线,尝试设置common_norm=True和multiple='stack'也没能得到理想的单图分色效果,请问如何在保持单密度图形态的前提下实现分色填充?
解决方案
Seaborn的kdeplot通过hue参数无法直接实现单密度图的左右分色,需要结合Matplotlib的fill_between函数手动填充区域。核心思路是:先绘制完整的密度曲线,提取曲线的x、y数据,再分别对0左侧和右侧的区域进行填充。
完整代码实现
import polars as pl import numpy as np import seaborn as sb import matplotlib.pyplot as plt import matplotlib.ticker as mtick TRIALS = int(10e3) RATE_A = 0.65 RATE_B = 0.66 SIMS = int(4e3) np.random.seed(42) # 生成模拟数据 df_sim = pl.DataFrame( { "A": np.random.binomial(TRIALS, RATE_A, SIMS) / TRIALS, "B": np.random.binomial(TRIALS, RATE_B, SIMS) / TRIALS, } ).with_columns((pl.col("B") - pl.col("A")).alias("treat_B")) # 绘图风格设置 sb.set(style="whitegrid") sb.set(font_scale=2) # 初始化画布并绘制无填充的kde曲线 fig, ax = plt.subplots(figsize=(12, 8)) kde_line = sb.kdeplot( data=df_sim, x="treat_B", ax=ax, color="black" # 曲线颜色可自定义 ) # 提取密度曲线的坐标数据 line = kde_line.get_lines()[0] x_data = line.get_xdata() y_data = line.get_ydata() # 填充0左侧区域(红色) ax.fill_between(x_data, 0, y_data, where=(x_data <= 0), color="red", alpha=0.5) # 填充0右侧区域(蓝色) ax.fill_between(x_data, 0, y_data, where=(x_data >= 0), color="blue", alpha=0.5) # 图表美化 ax.set_xlabel("Simulated Sample Means for treat_B") ax.set_title('4e3 Simulated Samples for treat_B') ax.set_xticks(np.arange(-0.02, 0.04, 0.01)) ax.xaxis.set_major_formatter(mtick.PercentFormatter(1, 0)) ax.axvline(0, color='black', linestyle='--') # 添加0值参考竖线 plt.show()
关键步骤说明
- 绘制基础曲线:先绘制不带填充的kde曲线,确保曲线形态是完整的单密度图;
- 提取曲线数据:通过
get_lines()获取曲线的x、y坐标数组,为后续填充做准备; - 分区域填充:利用
fill_between的where参数指定填充范围,分别设置左右区域的颜色和透明度; - 图表优化:添加坐标轴标签、标题、刻度格式化及参考线,提升图表可读性。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

