如何让Matplotlib音频波形图X轴时间刻度自动适配精度?
解决方案
要实现X轴刻度随图形缩放自动切换精度(默认秒级,放大显示毫秒/微秒),可以放弃datetime64类型的时间戳,直接使用秒数作为X轴数值,再通过自定义格式化函数根据当前视图范围动态调整显示格式。以下是修改后的代码:
import numpy as np from matplotlib import pyplot as plt from matplotlib import dates as mdates from scipy.io import wavfile import functools def time_formatter(x, pos, ax): # 获取当前轴的显示范围和音频总时长 x_min, x_max = ax.get_xlim() display_duration = x_max - x_min total_duration = ax.get_lines()[0].get_xdata()[-1] # 根据总时长和显示范围选择格式 if total_duration >= 3600: # 音频时长≥1小时 if display_duration >= 1: # 显示到秒:HH:MM:SS hours = int(x // 3600) mins = int((x % 3600) // 60) secs = int(x % 60) return f"{hours:02d}:{mins:02d}:{secs:02d}" elif display_duration >= 0.001: # 显示到毫秒:HH:MM:SS.sss hours = int(x // 3600) mins = int((x % 3600) // 60) secs = x % 60 return f"{hours:02d}:{mins:02d}:{secs:.3f}" else: # 显示到微秒:HH:MM:SS.ffffff hours = int(x // 3600) mins = int((x % 3600) // 60) secs = x % 60 return f"{hours:02d}:{mins:02d}:{secs:.6f}" else: # 音频时长<1小时 if display_duration >= 1: # 显示到秒:MM:SS mins = int(x // 60) secs = int(x % 60) return f"{mins:02d}:{secs:02d}" elif display_duration >= 0.001: # 显示到毫秒:MM:SS.sss mins = int(x // 60) secs = x % 60 return f"{mins:02d}:{secs:.3f}" else: # 显示到微秒:MM:SS.ffffff mins = int(x // 60) secs = x % 60 return f"{mins:02d}:{secs:.6f}" # 读取音频文件 freq_audio_1, samples_1 = wavfile.read("audio1.wav") samples_1 = samples_1[:, 0] # 转为单声道 freq_audio_2, samples_2 = wavfile.read("audio2.wav") samples_2 = samples_2[:, 0] # 转为单声道 # 生成秒级时间戳(无需转datetime64) t_audio_1 = np.arange(0, len(samples_1)) / freq_audio_1 t_audio_2 = np.arange(0, len(samples_2)) / freq_audio_2 # 创建画布和轴 fig, ax = plt.subplots(1, 2, constrained_layout=True) # 为每个轴设置动态格式化函数 for axis in ax: # 绑定当前轴对象到格式化函数 formatter = plt.FuncFormatter(functools.partial(time_formatter, ax=axis)) axis.xaxis.set_major_formatter(formatter) # 自动调整刻度数量,避免重叠 axis.xaxis.set_major_locator(mdates.AutoLocator()) # 绘制波形 ax[0].plot(t_audio_1, samples_1) ax[1].plot(t_audio_2, samples_2) plt.show()
关键改动说明
- 放弃datetime64类型:直接使用秒数作为X轴数值,避免datetime类型带来的刻度格式化限制,更灵活控制显示逻辑。
- 动态格式化函数:
- 通过
ax.get_xlim()获取当前视图的显示范围,判断是否需要显示更高精度(毫秒/微秒)。 - 根据音频总时长自动切换小时级格式(HH:MM:SS)或分钟级格式(MM:SS)。
- 通过
- 刻度优化:配合
AutoLocator自动调整刻度数量,从根源避免刻度重叠问题。
内容的提问来源于stack exchange,提问作者RomainP
相关产品推荐
相关产品推荐

