如何绘制DataFrame中actual与calculated列的并列对比直方图?
问题描述
现有如下Pandas DataFrame:
import pandas as pd df = pd.DataFrame( {'id': [1, 2, 3, 4, 5], 'actual': [412.6,741.24,1098.30,20025.87,1506.0], 'calculated': [315.24,517.61,998.38,7438.03,1503.32]} )
输出的DataFrame内容:
id actual calculated 0 1 412.60 315.24 1 2 741.24 517.61 2 3 1098.30 998.38 3 4 20025.87 7438.03 4 5 1506.00 1503.32
想要绘制actual与calculated列的并列条形图(对比每个id对应的具体数值),但以下代码未达到预期效果:
import matplotlib.pyplot as plt import numpy as np fig, ax = plt.subplots() a_heights, a_bins = np.histogram(df['actual']) b_heights, b_bins = np.histogram(df['calculated'], bins=a_bins) width = (a_bins[1] - a_bins[0])/3 ax.bar(a_bins[:-1], a_heights, width=width, facecolor='cornflowerblue') ax.bar(b_bins[:-1]+width, b_heights, width=width, facecolor='seagreen')
需求是Y轴显示对应数值(如412.60/315.24、741.24/517.61等),以下是正确实现方法:
正确实现方法
你需要的是并列条形图(而非统计频率的直方图),原代码错误使用了np.histogram(该函数用于统计数据频率分布),下面提供两种可行方案:
方案1:Pandas内置绘图(简洁版)
利用Pandas的plot.bar()可以直接生成并列条形图,代码更简洁:
import matplotlib.pyplot as plt import pandas as pd df = pd.DataFrame( {'id': [1, 2, 3, 4, 5], 'actual': [412.6,741.24,1098.30,20025.87,1506.0], 'calculated': [315.24,517.61,998.38,7438.03,1503.32]} ) # 将id设为索引,以id作为X轴标签 df.set_index('id')[['actual', 'calculated']].plot(kind='bar', figsize=(8,6)) plt.ylabel('数值') plt.title('Actual vs Calculated 数值对比') plt.legend(title='类别') plt.show()
方案2:Matplotlib手动绘制(自定义版)
如果需要更精细的样式控制,可以手动计算条形位置:
import matplotlib.pyplot as plt import pandas as pd import numpy as np df = pd.DataFrame( {'id': [1, 2, 3, 4, 5], 'actual': [412.6,741.24,1098.30,20025.87,1506.0], 'calculated': [315.24,517.61,998.38,7438.03,1503.32]} ) x = np.arange(len(df['id'])) # X轴位置索引 width = 0.35 # 单个条形的宽度 fig, ax = plt.subplots(figsize=(8,6)) # 绘制actual列的条形 rects1 = ax.bar(x - width/2, df['actual'], width, label='Actual', color='cornflowerblue') # 绘制calculated列的条形 rects2 = ax.bar(x + width/2, df['calculated'], width, label='Calculated', color='seagreen') # 设置X轴标签为id值 ax.set_xticks(x) ax.set_xticklabels(df['id']) ax.set_ylabel('数值') ax.set_title('Actual vs Calculated 数值对比') ax.legend(title='类别') # 可选:在条形上方显示具体数值 ax.bar_label(rects1, padding=3) ax.bar_label(rects2, padding=3) plt.show()
内容的提问来源于stack exchange,提问作者arilwan
相关产品推荐
相关产品推荐

