如何用带均值方差的Boxplot展示路口高低峰车流量并修正列名
问题:箱线图列名不生效,如何按路口ID展示高低峰车流量的均值方差?
我有包含路口ID、低峰/高峰时段车流量的数据,CSV列设置为1HT、1LT、2HT、2LT(数字是路口ID,HT=高峰,LT=低峰)。想要以路口ID为X轴,用箱线图展示各路口高低峰车流量的均值和方差,但现有代码生成的箱线图列名不生效,请问怎么实现?是否需要修改CSV格式?
用户提供的代码:
import pandas as pd import matplotlib.pyplot as plt from scipy import stats df=pd.read_csv("name1.csv") print(df) means=df.mean() var=df.var() q1=means+ var * stats.norm.ppf(0.25) q3=means+ var * stats.norm.ppf(0.75) whislow = q1 - (q3-q1) *1.5 whishi = q1 + (q3-q1) *1.5 cl=df.columns print("cl",cl) plt.xticks(range(1,len(df.columns)+1),cl,rotation='vertical') keys = ['med','q1','q3','whislo','whishi'] stats = [dict(zip(keys,vals)) for vals in zip(means,q1,q3,whislow,whishi)] plt.subplot().bxp(stats,showfliers=False) plt.show()
解决方案
1. CSV格式是否需要修改?
不需要大规模修改,当前1HT/1LT的命名逻辑可行。如果后续需要按路口ID分组对比高低峰流量,可将数据转为长格式(新增路口ID、时段类型、车流量三列),但当前格式也能直接完成需求。
2. 代码问题分析与修复
列名不生效的核心原因:plt.subplot().bxp()会重新创建坐标轴,覆盖了之前设置的xticks。另外,你手动计算箱线图统计量的逻辑有误——箱线图的分位数应基于原始数据分布计算,而非用均值+方差拟合正态分布(这是假设数据服从正态分布的近似,不符合箱线图的统计定义)。
修复后的最简代码:
import pandas as pd import matplotlib.pyplot as plt # 读取数据 df = pd.read_csv("name1.csv") print(df) # 直接用pandas内置boxplot方法,自动计算正确的分位数、均值等统计量 ax = df.boxplot(column=df.columns, showfliers=False) # 设置X轴标签并旋转,避免重叠 ax.set_xticklabels(df.columns, rotation='vertical') # 添加图表标注 ax.set_title('各路口高低峰车流量分布') ax.set_xlabel('路口-时段') ax.set_ylabel('车流量') plt.tight_layout() plt.show()
3. 进阶:按路口ID分组对比高低峰
如果希望X轴仅显示路口ID,每个ID下同时展示高峰/低峰两个箱线图,可先将数据转成长格式再绘制:
import pandas as pd import matplotlib.pyplot as plt # 读取数据并转成长格式 df = pd.read_csv("name1.csv") df_long = df.melt(var_name='路口-时段', value_name='车流量') # 从列名拆分出路口ID和时段类型 df_long[['路口ID', '时段']] = df_long['路口-时段'].str.extract('(\d+)(HT|LT)') # 按路口ID分组,绘制高低峰对比箱线图 ax = df_long.boxplot(by='路口ID', column='车流量', hue='时段', showfliers=False) # 调整图表样式 plt.suptitle('') # 移除自动生成的总标题 ax.set_title('各路口高低峰车流量对比') ax.set_xlabel('路口ID') ax.set_ylabel('车流量') plt.tight_layout() plt.show()
内容的提问来源于stack exchange,提问作者Sona S
相关产品推荐
相关产品推荐

