Pandas/Matplotlib绘图如何排除空值消除柱状图空白
问题根因
空白占位是最后一步透视表逻辑导致的:三个年份的Top5数据拼接后做pivot_table,会把所有出现过的7个国家全部转为列,未进入当年Top5的国家对应值为NaN,pandas内置的分组柱状图默认会给所有列预留柱位,NaN值就会显示为空白。不需要拆分成多个子图就能解决。
另外原代码中# create pivot table注释下对全量df做透视的代码没有被后续逻辑调用,可以直接删除。
修复方案
放弃pandas自动生成分组柱的逻辑,手动控制每个年份组的柱位置,按年份分别绘制对应Top5的柱即可,每个年份组固定显示5个有效柱,不会预留空白位。同时给国家分配固定颜色,保证跨年份对比时同一个国家颜色一致,对图例做去重避免重复显示。
完整可运行代码如下:
import pandas as pd import numpy as np import matplotlib.pyplot as plt # 读取数据、过滤区域聚合实体 df = pd.read_csv('~/Python/Projects/Jupyter Notebooks/Jupyter Notes and Exercises/Exercises/Energy Exercises/archive/wind-generation.csv') df = df.drop('Code', axis=1) df = df[~df['Entity'].isin(['OECD', 'Non-OECD', 'North America', 'South & Central America', 'Europe', 'Asia Pacific', 'European Union', 'World', 'Africa', 'Upper-middle-income countries','G20','G7', 'European Union (27)','High-income countries','Asia', 'Lower-middle-income countries','Latin America and Caribbean','South America'])] # 批量提取三个年份的Top5数据 target_years = [2000, 2010, 2020] year_data = {} all_countries = set() for y in target_years: top5_df = df[df['Year'] == y].sort_values('Electricity from wind (TWh)', ascending=False).head(5) year_data[y] = (top5_df['Entity'].tolist(), top5_df['Electricity from wind (TWh)'].tolist()) all_countries.update(top5_df['Entity'].tolist()) # 为每个国家分配固定配色 color_map = plt.cm.tab10 country_color = {c: color_map(i) for i, c in enumerate(all_countries)} bar_w = 0.15 group_gap = 0.3 # 不同年份组之间的间距 fig, ax = plt.subplots(figsize=(8,4)) # 逐年份绘制柱 for idx, y in enumerate(target_years): country_list, val_list = year_data[y] # 计算当前年份组5个柱的x坐标 x = np.arange(5) + idx*(5*bar_w + group_gap) bars = ax.bar(x, val_list, width=bar_w) # 按国家设置颜色、绑定标签 for bar, c in zip(bars, country_list): bar.set_color(country_color[c]) bar.set_label(c) # 配置坐标轴和标题 ax.set_xticks([np.arange(5).mean() + i*(5*bar_w + group_gap) for i in range(len(target_years))]) ax.set_xticklabels(target_years, rotation=0) ax.set_xlabel('Year') ax.set_ylabel('Wind Generation (TWh)') ax.set_title('Generation of Wind Energy by \nTop 5 Wind Energy-Producing Countries') ax.grid(True, axis='y') # 去重图例,放在图外侧避免遮挡 handles, labels = ax.get_legend_handles_labels() ax.legend(dict(zip(labels, handles)).values(), dict(zip(labels, handles)).keys(), bbox_to_anchor=(1.02, 1), loc='upper left') plt.tight_layout() plt.savefig('Wind Energy Top 5.png', facecolor='white') plt.show()
效果说明
- 每个年份分组固定显示5个柱,不存在空白占位
- 同一国家在不同年份的柱颜色统一,方便跨期对比
- 年份组之间保留了足够间距,不会出现柱重叠
- 图例自动去重,不会重复展示相同国家条目
内容的提问来源于stack exchange,提问作者Exquisite_Poupon
相关产品推荐
相关产品推荐

