绘制奥运奖牌饼图时遇AttributeError与ValueError问题求助
解决奥运奖牌饼图Python代码中的两个报错问题
我来帮你逐个拆解并解决这两个报错:
第一个错误:ValueError: Length mismatch: Expected axis has 2 elements, new values have 3 elements
问题根源
看你代码里这段操作:
final_df.reset_index(inplace=True) final_df.columns=('location','Total cases','Total Deaths')
在执行reset_index之后,final_df其实只有2列——原来的索引列Country,加上你通过iloc[:,[14]]选取的TotalMedal列。但你给了3个列名,列数和列名数量不匹配,自然就触发了这个错误。
修复方法
如果你只是需要国家和总奖牌数这两列,要么直接跳过手动改列名的步骤(重置索引后列名会自动是Country和TotalMedal,完全贴合你的需求),要么把列名改成对应2个元素的元组:
# 方案1:保留默认列名,最省心 final_df.reset_index(inplace=True) # 方案2:如果一定要自定义列名,用2个元素的元组 final_df.columns=('Country', 'TotalMedal')
第二个错误:AttributeError: 'DataFrameGroupBy' object has no attribute 'sort_values'
问题根源
这个错误说明你在一个**分组后的对象(DataFrameGroupBy)**上调用了sort_values,但分组对象本身没有这个方法。结合你的代码来看,大概率是两种情况之一:
- 你可能在代码里做了
groupby分组操作(但没贴出来),直接对分组结果调用sort_values; - 读取CSV时的分隔符设置错了——你用了
sep=' ',但奥运数据的CSV一般是逗号分隔的,这会导致pandas读取的DataFrame结构混乱,甚至意外出现类似分组的异常对象。
修复方法
- 如果是第一种情况(确实做了分组):先对分组结果做聚合(比如求和、取均值)得到普通DataFrame,再调用
sort_values:# 示例:按国家分组后聚合总奖牌数,再排序 grouped_df = df.groupby('Country')['TotalMedal'].sum().reset_index() sorted_df = grouped_df.sort_values(by='TotalMedal') - 如果是第二种情况(分隔符错误):把
sep=' '改成逗号分隔,或者让pandas自动推断分隔符:# 方法1:让pandas自动推断分隔符 df = pd.read_csv('data.csv', index_col=False, skipinitialspace=True, error_bad_lines=False, encoding='unicode_escape') # 方法2:明确指定逗号分隔 df = pd.read_csv('data.csv', sep=',', index_col=False, skipinitialspace=True, error_bad_lines=False, encoding='unicode_escape')
完整修正后的代码
结合你的需求(绘制Top10国家的奥运奖牌饼图),我整理了一份优化后的完整代码,同时去掉了冗余操作:
import pandas as pd import matplotlib.pyplot as plt def piechart1(): # 读取CSV,修正分隔符为逗号(适配大多数奥运数据格式) df = pd.read_csv('data.csv', sep=',', index_col=False, skipinitialspace=True, error_bad_lines=False, encoding='unicode_escape') # 直接选取需要的列(Country和TotalMedal),比用iloc硬编码列索引更鲁棒 df_filtered = df[['Country', 'TotalMedal']] # 按总奖牌数降序排序,取前10个国家 final_df = df_filtered.sort_values(by='TotalMedal', ascending=False).head(10) # 准备饼图所需的数据 countries = final_df['Country'] tmedals = final_df['TotalMedal'] # 绘制饼图 plt.pie(tmedals, labels=countries, explode=(0.1, 0, 0, 0, 0, 0, 0, 0, 0, 0), shadow=True, autopct='%0.1f%%') plt.title("Olympics Data Analysis\nTop 10 Countries by Total Medals", color='b', fontsize=12) plt.gcf().canvas.set_window_title("OLMPICS ANALYSIS") plt.show() # 调用函数生成饼图 piechart1()
额外优化说明
- 删掉了没用的
csv和numpy导入(你的代码里没用到它们); - 用列名直接选数据代替
iloc[:,[14]],避免因为CSV列顺序变化导致的错误; - 明确按降序排序并取前10,确保饼图展示的是真正的Top10国家;
- 修正了标题的拼写格式,看起来更规范。
内容的提问来源于stack exchange,提问作者Deepak Bhatt
相关产品推荐
相关产品推荐

