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

如何在Seaborn计数图中仅展示对应类别下有数据的文凭?

解决Seaborn Catplot子图仅显示对应职业存在的文凭问题

你的问题核心在于:Seaborn的catplot默认会使用整个数据集的所有文凭类别来生成每个子图,哪怕某个职业根本没有该文凭的记录,所以才会出现无关文凭显示的情况。而你之前尝试的query写法不仅语法有误(query里不需要加df[],直接用列名即可),而且逻辑上是全局筛选,无法实现按职业分组筛选的需求。

下面是实现每个子图仅显示对应职业存在文凭的完整解决方案:

步骤1:自定义FacetGrid绘制子图

我们需要用FacetGrid替代catplot,这样可以完全控制每个子图的数据源,只绘制当前职业下有数据的文凭:

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

# 假设你的数据框已经定义好
df = pd.DataFrame({
    'function': ['nurse', 'doctor', 'paediatric_nurse','kitchen_staff','surgeon'] * 7,
    'diploma': ['nurse_schoolA', 'doctor_schoolA', 'paed_nurse_schoolA', 'kitchen_certA', 'surgeon_schoolA',
                'nurse_schoolB', 'doctor_schoolB', 'paed_nurse_schoolB', 'kitchen_certB', 'surgeon_schoolB',
                'nurse_schoolC', 'doctor_schoolC', 'paed_nurse_schoolC', 'kitchen_certC', 'surgeon_schoolC',
                'nurse_schoolD', 'doctor_schoolD', 'paed_nurse_schoolD', 'kitchen_certD', 'surgeon_schoolD',
                'nurse_schoolE', 'doctor_schoolE', 'paed_nurse_schoolE', 'kitchen_certE', 'surgeon_schoolE',
                'nurse_schoolF', 'doctor_schoolF', 'paed_nurse_schoolF', 'kitchen_certF', 'surgeon_schoolF',
                'nurse_schoolG', 'doctor_schoolG', 'paed_nurse_schoolG', 'kitchen_certG', 'surgeon_schoolG']
})

# 创建FacetGrid,按function分栏,每行显示2个子图(可根据需求调整)
g = sns.FacetGrid(df, col='function', col_wrap=2, height=4)

# 定义每个子图的绘制函数
def plot_profession_diplomas(**kwargs):
    # 获取当前子图对应的职业
    current_profession = kwargs['data']['function'].iloc[0]
    # 筛选该职业的所有数据
    subset = df[df['function'] == current_profession]
    # 统计该职业下各文凭的计数
    diploma_counts = subset['diploma'].value_counts().reset_index()
    diploma_counts.columns = ['diploma', 'count']
    # 绘制水平条形图
    sns.barplot(data=diploma_counts, y='diploma', x='count', palette='viridis', **kwargs)

# 将绘制函数映射到每个子图
g.map_dataframe(plot_profession_diplomas)

# 美化布局和标题
g.set_titles(col_template='{col_name}')  # 设置子图标题为对应职业名称
g.fig.autofmt_xdate(rotation=45)  # 旋转x轴标签避免重叠
plt.tight_layout()
plt.show()

代码解释

  1. FacetGrid初始化:col='function'指定按职业分栏,col_wrap=2控制每行显示2个子图,避免子图过于拥挤。
  2. 自定义绘制函数:
    • 先获取当前子图对应的职业,筛选出该职业的数据集;
    • 用value_counts()统计该职业下每个文凭的数量;
    • 用sns.barplot绘制水平条形图(注意这里用y='diploma'、x='count'实现水平方向)。
  3. 布局调整:set_titles设置子图标题,autofmt_xdate旋转x轴标签,tight_layout优化整体布局。

为什么你的原代码不行?

你之前的df.query("df['diploma'].count()>0")存在两个问题:

  • query语法错误:在query中直接使用列名即可,不需要加df[],正确写法应该是query("diploma.notna()"),但这也只是全局筛选非空文凭,不是按职业分组筛选;
  • 逻辑错误:catplot的data参数是全局数据集,即使你做了全局筛选,它依然会使用所有文凭类别来生成子图,无法实现按职业动态显示对应文凭的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:27:22