
本文详解如何基于预定义的序位字典(如职业等级排名),对分类变量的频数分布进行排序并绘制结构清晰、语义准确的条形图(非传统直方图),涵盖排序逻辑、pandas索引对齐与matplotlib/seaborn可视化最佳实践。
本文详解如何基于预定义的序位字典(如职业等级排名),对分类变量的频数分布进行排序并绘制结构清晰、语义准确的条形图(非传统直方图),涵盖排序逻辑、pandas索引对齐与matplotlib/seaborn可视化最佳实践。
在数据分析中,当面对具有内在顺序但非数值型的分类变量(例如职业类别、教育等级、满意度评分)时,直接使用 hist() 绘制“直方图”不仅语义错误(直方图适用于连续数值分布),而且无法体现用户定义的序位逻辑。题中 occupation_rank 是一个典型的自定义序位映射字典——它赋予每个职业一个整数等级(1 最低,14 最高),目标应是:按该等级升序排列职业,并展示其在数据集中的实际频次。这本质上是一个有序条形图(ordered bar chart),而非直方图。
✅ 正确实现步骤
1. 获取原始频数分布(保持类别完整性)
首先用 pd.value_counts() 统计各职业出现频次,不提前排序,以保留原始类别信息:
import pandas as pd # 假设 adult_data 已加载 fd_occupation = pd.value_counts(adult_data['occupation']) # fd_occupation 是 Series,index=职业名,values=频次
2. 按自定义序位排序职业索引
关键一步:利用 occupation_rank 字典作为排序依据,对 fd_occupation.index 进行重排序。推荐使用 reindex() 确保严格对齐(比 sort_index() 更安全):
# 定义序位映射(注意键名需与数据中完全一致,含空格)
occupation_rank = {
' Farming-fishing': 1,
' Handlers-cleaners': 2,
' Priv-house-serv': 3,
' Other-service': 4,
' Adm-clerical': 5,
' Machine-op-inspct': 6,
' Transport-moving': 7,
' Craft-repair': 8,
' Sales': 9,
' Tech-support': 10,
' Protective-serv': 11,
' Armed-Forces': 12,
' Exec-managerial': 13,
' Prof-specialty': 14
}
# 按 occupation_rank 的键顺序重排频数 Series
sorted_fd = fd_occupation.reindex(occupation_rank.keys()).dropna()
# dropna() 可选:排除数据中不存在的职业(如字典中有但数据里没出现)⚠️ 注意:reindex() 要求字典键必须与 fd_occupation.index 中的值完全匹配(包括首尾空格)。若存在不一致,可先标准化:
adult_data['occupation'] = adult_data['occupation'].str.strip()
3. 绘制有序条形图(非直方图!)
使用 matplotlib 或 seaborn 绘制条形图,横轴为职业(按序位排列),纵轴为频次:
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
sorted_fd.plot(kind='barh', color='steelblue')
plt.xlabel('Frequency')
plt.ylabel('Occupation (Ordered by Rank)')
plt.title('Occupation Distribution Sorted by Custom Ordinal Rank')
plt.gca().invert_yaxis() # 可选:使 rank=1 在顶部(符合常规阅读习惯)
plt.tight_layout()
plt.show()或使用 Seaborn(更简洁且支持自动标签):
import seaborn as sns
df_plot = sorted_fd.reset_index(name='count')
df_plot['rank'] = df_plot['index'].map(occupation_rank) # 添加 rank 列便于理解
sns.barplot(data=df_plot, y='index', x='count', order=df_plot['index'])
plt.xlabel('Frequency')
plt.ylabel('Occupation')
plt.title('Occupation Frequency — Ordered by Predefined Rank')
plt.show()❌ 为什么原代码不适用?
- fd_occupation.hist(...) 尝试对分类索引的 Series 调用直方图,会报错或产生无意义的数值分箱;
- fd_occupation.sort_index() 是按职业名称字母序排序,与业务序位无关;
- 直方图(hist)本质是对连续数值变量进行等宽分箱计数,不适用于离散类别。
✅ 总结
- 概念澄清:序位排序的分类频数展示 → 用条形图(bar chart),非直方图(histogram);
- 核心操作:用 reindex(occupation_rank.keys()) 实现严格、可复现的顺序对齐;
- 健壮性建议:始终检查键名一致性(空格、大小写)、处理缺失类别;
- 进阶扩展:可将 occupation_rank 存为 DataFrame 并 merge 频数结果,便于后续添加描述性字段(如“初级”“高级”标签)。
通过以上方法,您即可生成一张既符合统计规范、又精准传达业务逻辑的有序职业分布图。










