如何用Matplotlib绘制含Yes/No分组的年龄频率直方图?
绘制Resigned分组(Yes/No)的年龄频率直方图问题解决
问题背景
已完成数据值计数,目标是用Matplotlib绘制分组直方图:X轴为年龄,Y轴为频率,"Yes"和"No"组用不同颜色。但现有代码执行后得到异常直方图。
数据与现有代码
数据预览
Resigned Age No 18 4 19 3 20 5 21 7 22 11 .. Yes 52 3 53 2 55 3 56 3 58 5 Length: 82, dtype: int64
完整计数数据(字典形式)
counts_dict = {('No', 18): 4, ('No', 19): 3, ('No', 20): 5, ('No', 21): 7, ('No', 22): 11, ('No', 23): 10, ('No', 24): 19, ('No', 25): 20, ('No', 26): 27, ('No', 27): 45, ('No', 28): 34, ('No', 29): 50, ('No', 30): 51, ('No', 31): 51, ('No', 32): 50, ('No', 33): 46, ('No', 34): 68, ('No', 35): 68, ('No', 36): 63, ('No', 37): 44, ('No', 38): 56, ('No', 39): 36, ('No', 40): 52, ('No', 41): 34, ('No', 42): 44, ('No', 43): 30, ('No', 44): 27, ('No', 45): 39, ('No', 46): 29, ('No', 47): 21, ('No', 48): 17, ('No', 49): 22, ('No', 50): 25, ('No', 51): 17, ('No', 52): 15, ('No', 53): 17, ('No', 54): 18, ('No', 55): 19, ('No', 56): 11, ('No', 57): 4, ('No', 58): 9, ('No', 59): 10, ('No', 60): 5, ('Yes', 18): 4, ('Yes', 19): 6, ('Yes', 20): 6, ('Yes', 21): 6, ('Yes', 22): 5, ('Yes', 23): 4, ('Yes', 24): 7, ('Yes', 25): 6, ('Yes', 26): 12, ('Yes', 27): 3, ('Yes', 28): 14, ('Yes', 29): 18, ('Yes', 30): 9, ('Yes', 31): 18, ('Yes', 32): 11, ('Yes', 33): 12, ('Yes', 34): 9, ('Yes', 35): 10, ('Yes', 36): 6, ('Yes', 37): 6, ('Yes', 38): 2, ('Yes', 39): 6, ('Yes', 40): 5, ('Yes', 41): 6, ('Yes', 42): 2, ('Yes', 43): 2, ('Yes', 44): 6, ('Yes', 45): 2, ('Yes', 46): 4, ('Yes', 47): 3, ('Yes', 48): 2, ('Yes', 49): 2, ('Yes', 50): 5, ('Yes', 51): 2, ('Yes', 52): 3, ('Yes', 53): 2, ('Yes', 55): 3, ('Yes', 56): 3, ('Yes', 58): 5}
现有代码
agereg_counts.plot(kind='hist', bins=30) # ratio data plt.title('Fig. 1 Revolution Consulting - Age Info') plt.xlabel('Age')
问题原因
现有代码直接对计数值调用直方图绘制,会把计数本身作为样本统计分布,而非以年龄为X轴、计数为Y轴展示分组频率,因此结果不符合预期。
解决方案
根据需求,推荐三种实现方式,按需选择:
1. 并列柱状图(展示每个年龄的分组频率)
适合离散年龄的精确对比:
import pandas as pd import matplotlib.pyplot as plt # 转换数据为宽格式DataFrame df = pd.Series(counts_dict).unstack(level=0, fill_value=0) ages = df.index x_pos = range(len(ages)) bar_width = 0.35 # 绘制并列柱子 fig, ax = plt.subplots(figsize=(12,6)) ax.bar([x - bar_width/2 for x in x_pos], df['No'], bar_width, label='No', color='#1f77b4') ax.bar([x + bar_width/2 for x in x_pos], df['Yes'], bar_width, label='Yes', color='#ff7f0e') # 设置图表属性 ax.set_xlabel('Age') ax.set_ylabel('Frequency') ax.set_title('Fig. 1 Revolution Consulting - Age Info') ax.set_xticks(x_pos) ax.set_xticklabels(ages) ax.legend(title='Resigned') plt.tight_layout() plt.show()
2. 堆叠柱状图(展示每个年龄的总频率及分组占比)
适合观察各年龄的整体分布与分组构成:
import pandas as pd import matplotlib.pyplot as plt df = pd.Series(counts_dict).unstack(level=0, fill_value=0) df.plot(kind='bar', stacked=True, color=['#1f77b4', '#ff7f0e'], figsize=(12,6)) plt.xlabel('Age') plt.ylabel('Frequency') plt.title('Fig. 1 Revolution Consulting - Age Info') plt.legend(title='Resigned') plt.tight_layout() plt.show()
3. 分组直方图(按年龄区间统计频率)
如果需要将年龄划分为连续区间展示分布:
import pandas as pd import matplotlib.pyplot as plt # 将计数数据转换为原始长格式 long_data = [] for (resigned, age), cnt in counts_dict.items(): long_data.extend([(resigned, age)] * cnt) long_df = pd.DataFrame(long_data, columns=['Resigned', 'Age']) # 绘制分组直方图 plt.figure(figsize=(10,6)) plt.hist( [long_df[long_df['Resigned']=='No']['Age'], long_df[long_df['Resigned']=='Yes']['Age']], bins=10, # 可调整区间数量 label=['No', 'Yes'], color=['#1f77b4', '#ff7f0e'], alpha=0.7 # 透明度,方便查看重叠部分 ) plt.xlabel('Age') plt.ylabel('Frequency') plt.title('Fig. 1 Revolution Consulting - Age Info') plt.legend(title='Resigned') plt.show()
内容的提问来源于stack exchange,提问作者David A
相关产品推荐
相关产品推荐

