plt.annotate()函数解析(最清晰的解释)

Matplotlib标注技巧
该文章已生成可运行项目,

欢迎关注WX公众号:【程序员管小亮】

plt.annotate()函数用于标注文字。
plt.annotate(s='str',
	xy=(x,y) ,
	xytext=(l1,l2) ,
	...
)

参数:

  • s 为注释文本内容

  • xy 为被注释的坐标点

  • xytext 为注释文字的坐标位置

  • xycoords 参数如下:

    • figure points:图左下角的点
    • figure pixels:图左下角的像素
    • figure fraction:图的左下部分
    • axes points:坐标轴左下角的点
    • axes pixels:坐标轴左下角的像素
    • axes fraction:左下轴的分数
    • data:使用被注释对象的坐标系统(默认)
    • polar(theta,r):if not native ‘data’ coordinates t
  • weight 设置字体线型

    • {‘ultralight’, ‘light’, ‘normal’, ‘regular’, ‘book’, ‘medium’, ‘roman’, ‘semibold’, ‘demibold’, ‘demi’, ‘bold’, ‘heavy’, ‘extra bold’, ‘black’}
  • color 设置字体颜色

    • {‘b’, ‘g’, ‘r’, ‘c’, ‘m’, ‘y’, ‘k’, ‘w’}
    • ‘black’,'red’等
    • [0,1]之间的浮点型数据
    • RGB或者RGBA, 如: (0.1, 0.2, 0.5)、(0.1, 0.2, 0.5, 0.3)等
  • arrowprops #箭头参数,参数类型为字典dict

    • width:箭头的宽度(以点为单位)
    • headwidth:箭头底部以点为单位的宽度
    • headlength:箭头的长度(以点为单位)
    • shrink:总长度的一部分,从两端“收缩”
    • facecolor:箭头颜色
  • bbox给标题增加外框 ,常用参数如下:

    • boxstyle:方框外形
    • facecolor:(简写fc)背景颜色
    • edgecolor:(简写ec)边框线条颜色
    • edgewidth:边框线条大小
例子1:
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0, 6)
y = x * x

plt.plot(x, y, marker='o')
for xy in zip(x, y):
    plt.annotate("(%s,%s)" % xy, xy=xy, xytext=(-20, 10), textcoords='offset points')
plt.show()

在这里插入图片描述

例子2:

把weight参数改成heavy。

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0, 6)
y = x * x

plt.plot(x, y, marker='o')
for xy in zip(x, y):
    plt.annotate("(%s,%s)" % xy, xy=xy, xytext=(-20, 10), textcoords='offset points', weight='heavy')
plt.show()

在这里插入图片描述

例子3:

把color参数改成y。

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0, 6)
y = x * x

plt.plot(x, y, marker='o')
for xy in zip(x, y):
    plt.annotate("(%s,%s)" % xy, xy=xy, xytext=(-20, 10), textcoords='offset points', color='y')
plt.show()

在这里插入图片描述

例子4:

把arrowprops参数改成通过dict传入参数(facecolor = “r”, headlength = 10, headwidth = 30, width = 20)。

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0, 6)
y = x * x

plt.plot(x, y, marker='o')
for xy in zip(x, y):
    plt.annotate("(%s,%s)" % xy, xy=xy, xytext=(-20, 10), textcoords='offset points', 
    arrowprops = dict(facecolor = "r", headlength = 10, headwidth = 30, width = 20))
plt.show()

在这里插入图片描述

例子5:

把bbox参数改成通过dict传入参数(boxstyle=‘round,pad=0.5’, fc=‘yellow’, ec=‘k’,lw=1 ,alpha=0.5)。

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0, 6)
y = x * x

plt.plot(x, y, marker='o')
for xy in zip(x, y):
    plt.annotate("(%s,%s)" % xy, xy=xy, xytext=(-20, 10), textcoords='offset points', 
    bbox=dict(boxstyle='round,pad=0.5', fc='yellow', ec='k', lw=1, alpha=0.5)
plt.show()

在这里插入图片描述

例子6:

把arrowprops参数改成通过dict传入参数(facecolor=‘black’, shrink=0.05)。

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0, 6)
y = x * x

plt.plot(x, y, marker='o')
for xy in zip(x, y):
    plt.annotate('local max', xy=(2, 1), xytext=(3, 1.5), arrowprops=dict(facecolor='black', shrink=0.05))
plt.show()

在这里插入图片描述

python课程推荐。
在这里插入图片描述

本文章已经生成可运行项目
df_weekly = data[7] if len(data) > 6 else pd.DataFrame() if not df_weekly.empty: try: # 直接使用日期字符串,不进行datetime转换 this_week = df_weekly[df_weekly['本周销售额'].notnull()].copy() last_week = df_weekly[df_weekly['上周销售额'].notnull()].copy() if not this_week.empty and not last_week.empty: # 直接使用日期作为x轴标签 plt.figure(figsize=(10, 6)) # 绘制本周曲线(使用索引作为x值) plt.plot(range(len(this_week)), this_week['本周销售额'], color='red', marker='o', linestyle='-', linewidth=2, label='本周') # 添加本周数据标签 for i, sales in enumerate(this_week['本周销售额']): plt.annotate(f"{sales:.2f}", xy=(i, sales), xytext=(0, 10), textcoords="offset points", ha='center', fontsize=9, color='red') # 绘制上周曲线 plt.plot(range(len(last_week)), last_week['上周销售额'], color='green', marker='s', linestyle='-', linewidth=2, label='上周') # 添加上周数据标签 for i, sales in enumerate(last_week['上周销售额']): plt.annotate(f"{sales:.2f}", xy=(i, sales), xytext=(0, -15), textcoords="offset points", ha='center', fontsize=9, color='green') # 设置x轴标签为日期 plt.xticks(range(len(this_week)), this_week['日期'], rotation=45) plt.title('本周与上周每日销售对比', fontsize=12) plt.xlabel('日期', fontsize=10) plt.ylabel('销售额', fontsize=10) plt.grid(True, linestyle='--', alpha=0.7) plt.legend(fontsize=9) plt.tight_layout() # 保存图表 chart_buffer = BytesIO() plt.savefig(chart_buffer, format='png', dpi=150) plt.close() elements.append(Image(chart_buffer, width=8.5 * inch, height=5 * inch)) elements.append(Spacer(1, 0.2 * inch)) except Exception as e: print(f"生成周销售对比图时出错: {str(e)}") print("跳过周销售对比图生成") 横坐标改为星期
08-21
Traceback (most recent call last): File "c:\Users\Yeah\Desktop\数模\比赛\B题\附件\1.py", line 142, in <module> wavenumbers, reflectance = parse_data(file_path) ~~~~~~~~~~^^^^^^^^^^^ File "c:\Users\Yeah\Desktop\数模\比赛\B题\附件\1.py", line 14, in parse_data data_string = file.read() File "<frozen codecs>", line 325, in decode UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 15-16: invalid continuation byte import numpy as np import matplotlib.pyplot as plt from scipy.signal import find_peaks import os # 获取当前脚本所在目录 current_dir = os.path.dirname(os.path.abspath(__file__)) # 构建附件1的完整路径(请确保附件1与本脚本在同一目录下) file_path = os.path.join(current_dir, "附件1.xlsx") # 1. 数据解析函数 def parse_data(file_path): with open(file_path, 'r', encoding='utf-8') as file: data_string = file.read() # 分割字符串 parts = data_string.strip().split(";") # 初始化数据列表 wavenumbers = [] reflectance = [] # 解析数据 i = 0 while i < len(parts): if parts[i].startswith("波数"): # 提取波数值 wavenumber = float(parts[i].split(":")[1]) wavenumbers.append(wavenumber) # 检查下一个部分是否为反射率 if i + 1 < len(parts) and parts[i + 1].startswith("反射率"): # 提取反射率值 reflectance_value = float(parts[i + 1].split(":")[1]) reflectance.append(reflectance_value) i += 2 # 跳过已处理的波数和反射率 else: reflectance.append(np.nan) # 如果没有对应的反射率,添加NaN i += 1 else: i += 1 # 转换为numpy数组 wavenumbers = np.array(wavenumbers) reflectance = np.array(reflectance) return wavenumbers, reflectance # 2. 数据统计分析函数 def analyze_data(wavenumbers, reflectance): # 基本统计信息 print("数据总量: {} 组数据对".format(len(wavenumbers))) print("波数范围: {:.4f} - {:.4f} cm⁻¹".format(np.min(wavenumbers), np.max(wavenumbers))) print("反射率范围: {:.2f}% - {:.2f}%".format(np.nanmin(reflectance), np.nanmax(reflectance))) print("平均反射率: {:.2f}%".format(np.nanmean(reflectance))) print("反射率标准差: {:.2f}%".format(np.nanstd(reflectance))) # 寻找反射率峰值 # 先处理NaN值 valid_indices = ~np.isnan(reflectance) wavenumbers_valid = wavenumbers[valid_indices] reflectance_valid = reflectance[valid_indices] peaks, _ = find_peaks(reflectance_valid, height=np.nanmean(reflectance_valid), distance=20) print("\n检测到的反射率峰值位置(波数):") for i in peaks: print("- {:.2f} cm⁻¹: {:.2f}%".format(wavenumbers_valid[i], reflectance_valid[i])) return wavenumbers_valid, reflectance_valid, peaks # 3. 数据可视化函数 def visualize_data(wavenumbers, reflectance, peaks): # 创建图表 plt.figure(figsize=(14, 8)) # 绘制主图 plt.plot(wavenumbers, reflectance, label='反射率', color='blue', linewidth=2) # 标记峰值 for i in peaks: plt.plot(wavenumbers[i], reflectance[i], 'rX', markersize=10) plt.annotate(f'{wavenumbers[i]:.2f}', (wavenumbers[i], reflectance[i]), xytext=(5, 5), textcoords='offset points') # 添加标签和标题 plt.xlabel(' 波数 (cm⁻¹)', fontsize=12) plt.ylabel(' 反射率 (%)', fontsize=12) plt.title(' 波数与反射率关系图', fontsize=14) plt.grid(True, linestyle='--', alpha=0.7) plt.legend() # 设置x轴方向 plt.gca().invert_xaxis() # 添加统计信息 plt.text(0.02, 0.95, f'平均反射率: {np.mean(reflectance):.2f}%\n' f'反射率标准差: {np.std(reflectance):.2f}%', transform=plt.gca().transAxes, fontsize=10, verticalalignment='top', bbox=dict(boxstyle='round', facecolor='white', alpha=0.8)) # 显示图形 plt.tight_layout() plt.show() # 4. 局部放大图可视化函数 def zoom_in_plot(wavenumbers, reflectance, zoom_range=None): plt.figure(figsize=(12, 6)) # 绘制全图 plt.subplot(2, 1, 1) plt.plot(wavenumbers, reflectance, label='反射率', color='blue') plt.gca().invert_xaxis() plt.title(' 全图') plt.grid(True) # 绘制局部放大图 plt.subplot(2, 1, 2) if zoom_range: # 根据指定范围绘制 mask = (wavenumbers >= zoom_range[1]) & (wavenumbers <= zoom_range[0]) plt.plot(wavenumbers[mask], reflectance[mask], label='反射率', color='blue') plt.title(f' 局部放大图 (波数: {zoom_range[0]}-{zoom_range[1]} cm⁻¹)') else: # 默认绘制反射率波动大的区域 max_index = np.argmax(np.gradient(reflectance, wavenumbers)) zoom_start = wavenumbers[max_index+10] zoom_end = wavenumbers[max_index-10] mask = (wavenumbers >= zoom_end) & (wavenumbers <= zoom_start) plt.plot(wavenumbers[mask], reflectance[mask], label='反射率', color='blue') plt.title(f' 反射率波动大区域 (波数: {zoom_start:.2f}-{zoom_end:.2f} cm⁻¹)') plt.gca().invert_xaxis() plt.grid(True) plt.tight_layout() plt.show() # 主程序 if __name__ == "__main__": # 读取和解析数据 wavenumbers, reflectance = parse_data(file_path) # 数据分析 wavenumbers_valid, reflectance_valid, peaks = analyze_data(wavenumbers, reflectance) # 数据可视化 visualize_data(wavenumbers_valid, reflectance_valid, peaks) # 局部放大图 zoom_in_plot(wavenumbers_valid, reflectance_valid)
09-05
为什么反射率波动大区域图像输出中没有曲线 import os import numpy as np import pandas as pd import matplotlib.pyplot as plt from scipy.signal import find_peaks plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False # 获取当前脚本所在目录 current_dir = os.path.dirname(os.path.abspath(__file__)) # 构建附件1的完整路径 file_path = os.path.join(current_dir, "附件1.xlsx") # 1. 数据解析函数 def parse_data(file_path): """ 从 Excel 文件中读取波数和反射率数据,并检查是否存在空值 :param file_path: Excel 文件路径 :return: 波数数组, 反射率数组 """ try: data = pd.read_excel(file_path, header=0) # 第一行作为列名 # 检查是否存在空值 if data.isna().any().any(): print("警告:文件中存在空值(NaN),请检查数据完整性!") print("空值统计:") print(data.isna().sum()) else: print("无空值") wavenumbers = data.iloc[:, 0].values # 第一列:波数 reflectance = data.iloc[:, 1].values # 第二列:反射率 return wavenumbers, reflectance except Exception as e: print(f"读取文件出错: {e}") return None, None # 2. 数据统计分析函数 def analyze_data(wavenumbers, reflectance): """ 输出数据的基本统计信息,并检测反射率峰值 :param wavenumbers: 波数数组 :param reflectance: 反射率数组 :return: 波数数组, 反射率数组, 峰值索引 """ print("数据总量: {} 组数据对".format(len(wavenumbers))) print("波数范围: {:.2f} - {:.2f} cm⁻¹".format(np.min(wavenumbers), np.max(wavenumbers))) print("反射率范围: {:.2f}% - {:.2f}%".format(np.min(reflectance), np.max(reflectance))) print("平均反射率: {:.2f}%".format(np.mean(reflectance))) print("反射率标准差: {:.2f}%".format(np.std(reflectance))) # 检测反射率峰值 peaks, _ = find_peaks(reflectance, height=np.mean(reflectance), distance=20) print("\n检测到的反射率峰值位置(波数):") for i in peaks: print("- {:.2f} cm⁻¹: {:.2f}%".format(wavenumbers[i], reflectance[i])) return wavenumbers, reflectance, peaks # 3. 数据可视化函数(主图 + 峰值标记) def visualize_data(wavenumbers, reflectance, peaks): """ 绘制波数与反射率关系图,并标记峰值 :param wavenumbers: 波数数组 :param reflectance: 反射率数组 :param peaks: 峰值索引数组 """ plt.figure(figsize=(14, 8)) plt.plot(wavenumbers, reflectance, label='反射率', color='blue', linewidth=1.5) # 标记峰值 for i in peaks: plt.plot(wavenumbers[i], reflectance[i], 'rX', markersize=8) plt.annotate(f'{wavenumbers[i]:.2f}', (wavenumbers[i], reflectance[i]), xytext=(5, 5), textcoords='offset points', fontsize=8) plt.xlabel('波数 (cm⁻¹)', fontsize=12) plt.ylabel('反射率 (%)', fontsize=12) plt.title('波数与反射率关系图', fontsize=14) plt.grid(True, linestyle='--', alpha=0.7) plt.legend() plt.gca().invert_xaxis() # 波数通常从高到低显示 # 添加统计信息 plt.text(0.02, 0.95, f'平均反射率: {np.mean(reflectance):.2f}%\n' f'反射率标准差: {np.std(reflectance):.2f}%', transform=plt.gca().transAxes, fontsize=10, verticalalignment='top', bbox=dict(boxstyle='round', facecolor='white', alpha=0.8)) plt.tight_layout() plt.show() # 4. 局部放大图可视化函数 def zoom_in_plot(wavenumbers, reflectance, zoom_range=None): """ 绘制局部放大图 :param wavenumbers: 波数数组 :param reflectance: 反射率数组 :param zoom_range: 放大区域范围 (start, end) """ plt.figure(figsize=(12, 6)) plt.subplot(2, 1, 1) plt.plot(wavenumbers, reflectance, label='反射率', color='blue') plt.gca().invert_xaxis() plt.title('全图') plt.grid(True) plt.subplot(2, 1, 2) if zoom_range: mask = (wavenumbers >= zoom_range[1]) & (wavenumbers <= zoom_range[0]) plt.plot(wavenumbers[mask], reflectance[mask], label='反射率', color='blue') plt.title(f'局部放大图 (波数: {zoom_range[0]}–{zoom_range[1]} cm⁻¹)') else: max_index = np.argmax(np.gradient(reflectance, wavenumbers)) zoom_start = wavenumbers[max_index + 10] zoom_end = wavenumbers[max_index - 10] mask = (wavenumbers >= zoom_end) & (wavenumbers <= zoom_start) plt.plot(wavenumbers[mask], reflectance[mask], label='反射率', color='blue') plt.title(f'反射率波动大区域 (波数: {zoom_start:.2f}–{zoom_end:.2f} cm⁻¹)') plt.gca().invert_xaxis() plt.grid(True) plt.tight_layout() plt.show() # 主程序 if __name__ == "__main__": # 1. 读取和解析数据 wavenumbers, reflectance = parse_data(file_path) if wavenumbers is not None and reflectance is not None: # 2. 数据分析 wavenumbers, reflectance, peaks = analyze_data(wavenumbers, reflectance) # 3. 数据可视化 visualize_data(wavenumbers, reflectance, peaks) # 4. 局部放大图 zoom_in_plot(wavenumbers, reflectance)
最新发布
09-05
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是管小亮

一口吃掉你的打赏,嗝~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值