如何使用Matplotlib在循环中为图表散点添加国家名称标注?
解决循环生成散点图并标注国家名称的问题
问题说明
需要在循环生成的每年散点图中,为每个散点标注对应的国家名称,但原代码无法正确实现该效果。
原代码存在的问题
- 列索引计算错误:
edff.iloc[i, year - 2000-n]中的索引逻辑错误,导致无法正确获取对应年份的数据列,标注位置完全偏差。 - 参考线重复绘制:
plt.plot([0,600],[0,600])放在内层循环中,会为每个点重复绘制一次参考线,冗余且影响性能。 - 对数刻度作用范围错误:
plt.xscale('log')和plt.yscale('log')放在循环外部,仅会对最后一张图表生效,前面的图表无法应用对数刻度。 - 缺少基础标识:每张图未添加年份标题、坐标轴标签,可读性差。
修正后的代码
import pandas as pd import matplotlib.pyplot as plt import csv # 生成测试数据 with open('edff.csv', 'w', newline='') as file: writer = csv.writer(file) writer.writerow(["Name", "2000", "2001", "2002"]) writer.writerow(["Afg", "500", "529","531"]) writer.writerow(["Alb", "125", "127","129"]) writer.writerow(["Alg", "52", "54", "55"]) with open('cdff.csv', 'w', newline='') as file: writer = csv.writer(file) writer.writerow(["Name", "2000", "2001", "2002"]) writer.writerow(["Afg", "501", "531","532"]) writer.writerow(["Alb", "124", "126","130"]) writer.writerow(["Alg", "50", "52", "55"]) # 读取数据 edff = pd.read_csv("edff.csv") cdff = pd.read_csv("cdff.csv") # 获取年份列表(跳过第一列Name) years = edff.columns.tolist()[1:] years = [int(year) for year in years] for year in years: plt.figure(figsize=(9, 6)) # 获取当前年份的数值列 x_values = edff[str(year)] y_values = cdff[str(year)] # 绘制散点图 plt.scatter(x_values, y_values, alpha=0.5) # 遍历每个国家,标注名称 for idx, row in edff.iterrows(): country_name = row['Name'] # 在散点右侧稍偏移位置标注,避免遮挡 plt.text(x_values.iloc[idx] * 1.02, y_values.iloc[idx], country_name, fontsize=10) # 绘制参考线 plt.plot([0, 600], [0, 600], color='gray', linestyle='--') # 设置图表属性 plt.title(f"Year {year}") plt.xlabel("EDFF Value") plt.ylabel("CDFF Value") plt.xscale('log') plt.yscale('log') plt.xlim(40, 600) # 适配数据调整轴范围 plt.ylim(40, 600) plt.grid(True, alpha=0.3) plt.show()
关键改进点
- 使用
iterrows()遍历数据行,直接获取国家名称和对应年份的数值,彻底避免索引计算错误。 - 将参考线绘制、图表属性设置移到外层循环,确保每张图只绘制一次参考线并正确应用对数刻度。
- 添加年份标题、坐标轴标签和网格,提升图表可读性。
- 调整标注位置为散点右侧稍偏移处,避免遮挡散点本身。
内容的提问来源于stack exchange,提问作者Alma
相关产品推荐
相关产品推荐

