Pandas中plot.line()绘制分类数值型x轴的问题
问题
我想要创建一个折线图,x轴仅显示分类数值型的1.0、2.0、3.0这三个值,但运行以下代码后,x轴显示的是0.5-3.5的数值范围,求解决方法:
fig, axes = plt.subplots(nrows=2) fig.tight_layout(pad=3.2) newdata = newdf.groupby('smoking-number').mean().reset_index() sem = newdf.groupby('smoking-number').sem().reset_index() newdata.plot.line(x='smoking-number',y='distance', yerr= sem, ax=axes[0],legend=False) newdata.plot.line(x='smoking-number',y='duration', yerr= sem, ax=axes[1],legend=False) upperbounddistance = max(newdata[['distance']].values)+max(sem[['distance']].values) lowerbounddistance = min(newdata[['distance']].values)-min(sem[['distance']].values) upperboundduration = max(newdata[['duration']].values)+max(sem[['duration']].values) lowerboundduration = min(newdata[['duration']].values)-min(sem[['duration']].values) axes[0].set_ylim(lowerbounddistance,upperbounddistance) axes[0].set_xlim(0.5,3.5) axes[1].set_ylim(lowerboundduration,upperboundduration) axes[1].set_xlim(0.5,3.5) axes[0].set_ylabel("Wayfinding distance") axes[0].set_xlabel("Smoking frequency") axes[1].set_ylabel("Wayfinding duration") axes[1].set_xlabel("Smoking frequency")
数据示例:
distance 10 48.146090 13 98.877301 17 66.670310 19 95.764316 21 78.737108 22 48.404197 25 63.910073 27 40.862231 28 50.223985 30 38.724922 duration 10 40.976006 13 90.093298 17 88.349603 19 82.737323 21 72.579054 22 40.059987 25 57.629693 27 38.419589 28 40.834470 30 34.813547 smoking-number 10 1.0 13 1.0 17 1.0 19 1.0 21 1.0 22 1.0 25 3.0 27 1.0 28 1.0 30 1.0
解决方案
问题根源有两个:一是你手动设置了xlim(0.5,3.5)强制扩展了x轴范围;二是matplotlib默认将数值型的smoking-number当作连续数值轴处理,而非分类轴。
修改步骤如下:
- 移除两行
set_xlim(0.5,3.5)代码,取消强制范围限制 - 将
smoking-number转换为字符串类型,让matplotlib识别为分类变量 - 手动指定x轴刻度和标签,确保只显示1.0、2.0、3.0三个值
修改后的完整代码:
import matplotlib.pyplot as plt import pandas as pd fig, axes = plt.subplots(nrows=2) fig.tight_layout(pad=3.2) newdata = newdf.groupby('smoking-number').mean().reset_index() sem = newdf.groupby('smoking-number').sem().reset_index() # 将smoking-number转为字符串,标记为分类 newdata['smoking-number'] = newdata['smoking-number'].astype(str) sem['smoking-number'] = sem['smoking-number'].astype(str) newdata.plot.line(x='smoking-number', y='distance', yerr=sem, ax=axes[0], legend=False) newdata.plot.line(x='smoking-number', y='duration', yerr=sem, ax=axes[1], legend=False) upperbounddistance = max(newdata[['distance']].values) + max(sem[['distance']].values) lowerbounddistance = min(newdata[['distance']].values) - min(sem[['distance']].values) upperboundduration = max(newdata[['duration']].values) + max(sem[['duration']].values) lowerboundduration = min(newdata[['duration']].values) - min(sem[['duration']].values) axes[0].set_ylim(lowerbounddistance, upperbounddistance) axes[1].set_ylim(lowerboundduration, upperboundduration) # 手动设置x轴刻度和标签,确保显示目标值 target_x = ['1.0', '2.0', '3.0'] for ax in axes: ax.set_xticks(range(len(target_x))) ax.set_xticklabels(target_x) ax.set_xlabel("Smoking frequency") axes[0].set_ylabel("Wayfinding distance") axes[1].set_ylabel("Wayfinding duration") plt.show()
补充说明
- 转换为字符串后,matplotlib会将x轴视为离散分类,自动只显示数据中存在的类别(如果你的数据里没有2.0,代码依然会显示该标签但无对应折线点,可根据实际数据调整
target_x列表) - 手动设置刻度能确保即使数据中缺失某个分类(比如2.0),x轴依然会显示该标签,符合你的需求
内容的提问来源于stack exchange,提问作者Caledonian26
相关产品推荐
相关产品推荐

