如何用matplotlib/seaborn正确绘制分国家分品类的周度出口趋势折线图
现有代码问题排查
- 绘图参数逻辑错位:循环里传入
sns.lineplot的数据集是转置后的宽表,指定的x值WeekEndingDate、y值weekly export均不是该数据集的有效列名,会直接触发参数匹配错误,无法正常渲染折线。 - Top5贸易国筛选规则不符合需求:代码通过删除累计出口低于1000的国家做数据过滤,既没有按出口规模排名精准选出前5大贸易伙伴,固定1000的数值阈值也不具备跨数据集的适配性,完全偏离核心目标。
- 时间序列属性丢失:读入的
weekEndingDate为字符串格式,没有转换为datetime类型,绘图时会被识别为普通离散分类值,无法实现时间轴的自动排序、间隔适配,最终导致x轴文字拥挤、折线顺序错位。 - 冗余的逐列绘图逻辑:宽表场景下逐列循环调用
sns.lineplot,不仅代码执行效率低,还容易触发图例重复渲染的问题,seaborn原生支持通过长表输入一次性完成多组折线的绘制。 - 视觉细节适配缺失:没有对出口额这类大数值做千分位格式优化,没有配置x轴日期的旋转防重叠,也没有按简洁风格隐藏冗余的图表边框,最终视觉效果和参考样式差距明显。
优化后实现方案(基于matplotlib + seaborn)
整体逻辑遵循「数据类型转换→按品类筛选Top5贸易国→一次性渲染折线」的流程,兼顾可读性和绘图效率,可直接运行的代码如下:
import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from matplotlib.ticker import FuncFormatter # 配置绘图风格,对齐简洁参考样式 sns.set_style("ticks") plt.rcParams["font.sans-serif"] = ["SimHei"] # 适配中文显示 plt.rcParams["axes.unicode_minus"] = False # 1. 数据读取与基础清洗 url = 'https://gist.githubusercontent.com/adamFlyn/e9ad428a266eccb5dc38b4cee7084372/raw/cfcbe9cf0ed19ada6a4ea409644db7414de9c87f/sales_df.csv' df = pd.read_csv(url) df.drop(columns=['Unnamed: 0'], inplace=True) # *关键修复:转换周度日期为标准时间类型,从根源解决时间轴错位问题 df['weekEndingDate'] = pd.to_datetime(df['weekEndingDate']) df = df.sort_values('weekEndingDate') # 2. 逐品类绘制对应折线图 target_commodities = ['FCF_Beef', 'FCF_Pork'] for commodity in target_commodities: # 筛选当前品类的有效数据 sub_df = df[df['commodity'] == commodity] # 计算每个国家的总出口额,取Top5贸易国 country_total = sub_df.groupby('country')['weeklyExports'].sum().sort_values(ascending=False) top5_countries = country_total.head(5).index.tolist() # 过滤仅保留Top5国家的周度数据 plot_df = sub_df[sub_df['country'].isin(top5_countries)] # 3. 初始化画布 fig, ax = plt.subplots(figsize=(9, 5), dpi=144) # 一次性绘制分组折线,不需要逐列循环 sns.lineplot( x='weekEndingDate', y='weeklyExports', hue='country', data=plot_df, ci=None, linewidth=1.8, ax=ax ) # 4. 视觉细节优化 ax.set_title(f"{commodity} 周度出口趋势(Top5贸易国)", fontsize=12, pad=15) ax.set_xlabel("", fontsize=10) ax.set_ylabel("周度出口规模", fontsize=10) # Y轴千分位格式适配大数值 ax.yaxis.set_major_formatter(FuncFormatter(lambda x, pos: f"{int(x):,}")) # X轴日期旋转避免重叠 plt.xticks(rotation=30, ha='right') # 图例放在右侧避免遮挡折线 ax.legend(bbox_to_anchor=(1.02, 1), loc='upper left', frameon=False) # 仅保留浅灰色横向网格,去掉冗余边框 ax.grid(axis='y', alpha=0.3, linestyle='--') sns.despine() plt.tight_layout() plt.show() plt.close()
方案说明
- 全程采用符合seaborn输入要求的长表格式传参,彻底解决原代码的参数不匹配报错问题
- Top5国家筛选严格按对应品类的累计出口额排名选取,不再依赖无依据的固定阈值,适配不同规模的数据集
- 内置日期类型转换逻辑,时间轴会自动根据周度粒度生成合理的刻度间隔,不会出现文字拥挤、顺序错乱的问题
- 视觉配置完全对齐参考图的简洁风格:无冗余边框、浅灰色横向网格、右侧不遮挡折线的悬浮图例、千分位格式的大数值显示
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

