如何从列表创建Pandas DataFrame并绘制veh_class的cmb_mpg比例柱状图
解决2008/2018车型油耗比例可视化的问题
首先说下核心问题:你现在生成的是字符串格式的列表,既没法直接用pandas的plot方法(这就是触发AttributeError的原因),还包含无效的nan值。下面给你两种可行的解决方案,优先推荐用结构化DataFrame的方式,更简洁易维护。
方案一:创建可直接绘图的DataFrame
这是最推荐的方式,我们直接收集车型类别和对应比例的结构化数据,转成DataFrame并处理无效值后,就能轻松完成绘图。
修改后的代码
import pandas as pd import matplotlib.pyplot as plt # 初始化空列表存储结构化数据 prop_data = [] vehicle_classes = df_18["veh_class"].unique() for v_class in vehicle_classes: # 获取两个年份对应类别的平均油耗 cmb_mpg_08 = df_08[df_08['veh_class'] == v_class]['cmb_mpg'].mean() cmb_mpg_18 = df_18[df_18['veh_class'] == v_class]['cmb_mpg'].mean() # 处理NaN和除数为0的情况,避免生成无效比例 if pd.notna(cmb_mpg_08) and cmb_mpg_08 > 0: proportion = cmb_mpg_18 / cmb_mpg_08 else: proportion = None # 也可以用0填充,根据你的需求调整 # 用字典存储数据,方便后续转换为DataFrame prop_data.append({"veh_class": v_class, "mpg_proportion": proportion}) # 转换为结构化DataFrame prop_df = pd.DataFrame(prop_data) # 删除包含NaN的行(这些是2008年没有对应数据的车型,比例无意义) prop_df = prop_df.dropna(subset=["mpg_proportion"])
为什么这么改?
- 不再生成字符串,而是用字典保存车型类别和比例值,转成DataFrame后直接支持pandas的
plot方法 - 增加了无效数据的处理逻辑,避免NaN干扰后续绘图
- 生成的
prop_df结构清晰,后续做排序、过滤等二次分析也更便捷
绘制柱状图
有了结构化DataFrame,绘图就非常简单了:
# 设置绘图风格(可选,让图表更美观) plt.style.use('seaborn-v0_8') # 绘制柱状图 prop_df.plot(kind='bar', x='veh_class', y='mpg_proportion', figsize=(10, 6)) # 自定义图表细节 plt.title('2018 vs 2008 Average Combined MPG Proportion by Vehicle Class') plt.xlabel('Vehicle Class') plt.ylabel('Proportion (2018 MPG / 2008 MPG)') plt.xticks(rotation=45, ha='right') # 旋转x轴标签,避免重叠 plt.tight_layout() # 自动调整布局,防止标签被截断 plt.show()
方案二:直接处理你生成的列表绘图(不推荐,但提供方法)
如果你不想修改原代码,想直接用生成的prop列表,需要先解析字符串中的类别和比例值,再用matplotlib手动绘图:
import matplotlib.pyplot as plt # 解析原列表中的数据 vehicle_classes = [] mpg_proportions = [] for item in prop: # 拆分字符串,提取车型类别和比例 cls, p_str = item.split(': ') # 过滤nan值,只保留有效数据 if p_str != 'nan': vehicle_classes.append(cls) mpg_proportions.append(float(p_str)) # 用matplotlib绘制柱状图 plt.figure(figsize=(10, 6)) plt.bar(vehicle_classes, mpg_proportions) # 添加图表标签和标题 plt.title('2018 vs 2008 Average Combined MPG Proportion by Vehicle Class') plt.xlabel('Vehicle Class') plt.ylabel('Proportion (2018 MPG / 2008 MPG)') plt.xticks(rotation=45, ha='right') plt.tight_layout() plt.show()
注意事项
- 原列表中的
nan是因为2008年没有对应车型的数据,这些比例没有实际意义,绘图前一定要过滤掉 - 相比方案一,这种方法需要手动解析数据,后续维护和调整都更麻烦,所以优先推荐用DataFrame的方式
内容的提问来源于stack exchange,提问作者Authentic Equipment
相关产品推荐
相关产品推荐

