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

Seaborn:多FacetGrid按4×4网格排列的实现问题求助

解决Seaborn FacetGrid多分类列分组countplot布局问题

我明白你想要实现的效果:16个分类特征,每个特征对应两张countplot(分别展示Y=0和Y=1时的类别分布),然后把这16组共32张图整理成4×4的网格布局(每组占一个网格位置)。先帮你分析下之前两种方法失败的原因:

  • 方法一:FacetGrid本身会自动创建独立的Figure和Axes对象,你手动指定ax=ax会和FacetGrid的内部布局逻辑冲突,所以无法正常渲染。
  • 方法二:同一个FacetGrid实例重复调用map会覆盖之前的绘图内容,最终只会保留最后一次调用的结果。

下面给你两种可行的解决方案,你可以根据自己的布局偏好选择:

方案一:手动嵌套布局(同一特征的两张图并排)

这种方案会让每个特征的Y=0/Y=1子图在同一个网格单元里并排展示,视觉上更紧凑,方便对比同一特征在不同Y类别下的分布:

import seaborn as sbn
import matplotlib.pyplot as plt
import pandas as pd

# 先提取所有特征列(排除目标列Y)
feature_cols = [col for col in df.columns if col != "Y"]

# 创建4×4的大网格布局
fig, big_axes = plt.subplots(4, 4, figsize=(20, 15))

for col, big_ax in zip(feature_cols, big_axes.flat):
    # 设置当前特征的大标题
    big_ax.set_title(f"特征: {col}", fontsize=14)
    # 隐藏大轴的刻度和边框,避免干扰内部子图
    big_ax.tick_params(labelleft=False, labelbottom=False, bottom=False, left=False)
    big_ax.spines[['top', 'right', 'bottom', 'left']].set_visible(False)
    
    # 在大轴内创建两个并排的子轴(调整参数控制位置和大小)
    ax_y0 = big_ax.inset_axes([0.05, 0.1, 0.42, 0.8])  # [x起始, y起始, 宽度, 高度]
    ax_y1 = big_ax.inset_axes([0.53, 0.1, 0.42, 0.8])
    
    # 绘制Y=0的countplot
    sbn.countplot(data=df[df["Y"] == 0], x=col, ax=ax_y0)
    ax_y0.set_title("Y=0")
    ax_y0.tick_params(axis='x', rotation=45)  # 旋转x轴标签避免重叠
    
    # 绘制Y=1的countplot
    sbn.countplot(data=df[df["Y"] == 1], x=col, ax=ax_y1)
    ax_y1.set_title("Y=1")
    ax_y1.tick_params(axis='x', rotation=45)

plt.tight_layout()
plt.show()

方案二:长格式数据+FacetGrid自动布局

这种方案利用Pandas的melt把宽格式数据转成长格式,再借助Seaborn的FacetGrid自动处理布局,代码更简洁,适合快速生成可视化:

import seaborn as sbn
import matplotlib.pyplot as plt
import pandas as pd

# 提取特征列并转换为长格式数据
feature_cols = [col for col in df.columns if col != "Y"]
melted_df = df.melt(
    id_vars=["Y"], 
    value_vars=feature_cols, 
    var_name="特征", 
    value_name="类别值"
)

# 创建FacetGrid:按特征分列,按Y分行,每4个特征换行
g = sbn.FacetGrid(
    melted_df, 
    col="特征", 
    row="Y", 
    col_wrap=4, 
    height=3, 
    aspect=1.2
)
# 映射countplot到每个子图
g.map(sbn.countplot, "类别值")

# 调整子图标题和x轴标签
for ax in g.axes.flat:
    ax.tick_params(axis='x', rotation=45)
    # 解析并设置更清晰的子图标题
    title_parts = ax.get_title().split(" | ")
    feature = title_parts[0].split(" = ")[1]
    y_val = title_parts[1].split(" = ")[1]
    ax.set_title(f"{feature}\nY={y_val}")

plt.tight_layout()
plt.show()

两种方案的小提示:

  • 如果你的分类列类别名称较长,记得保留rotation=45甚至改成rotation=90,避免标签重叠。
  • 可以根据需求调整figsize、height、aspect等参数,优化图表的整体大小和比例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 20:52:43