为何热力图出现异常深蓝色区域?仅(5,5)点z值为9
热力图异常区域与插值警告的解决方法
问题情况
测试Excel包含x、y、z三列数据,仅(5,5)点的z值为9,其余所有点z值均为1。使用jet色图生成热力图时,预期仅(5,5)为红色,其余区域为蓝色,但实际生成的图在(0,6)和(6,0)出现深蓝色异常区域,同时终端抛出如下警告:
RuntimeWarning: No more knots can be added because the additional knot would
coincide with an old one. Probable cause: s too small or too large
a weight to an inaccurate data point. (fp>s)
kx,ky=1,1 nx,ny=11,11 m=100 fp=46.439909 s=0.000000
warnings.warn(RuntimeWarning(_iermess2[ierm][0] + _mess))
原因分析
- 警告原因:
interp2d默认采用样条插值,当s=0(默认值)时要求插值函数严格经过所有数据点。若数据存在重复坐标,或插值边界处理逻辑冲突,会导致算法无法添加新节点,触发警告。 - 异常区域原因:
interp2d对边界外的插值行为不可控,后续imshow使用的bicubic插值进一步放大了边界误差,最终导致角落出现异常值。
解决方案
方案1:直接用网格数据绘图(推荐)
由于数据本身是规则网格点,无需额外插值,直接将数据整理为二维网格即可绘图:
import matplotlib.pyplot as plt import numpy as np import pandas as pd excel_data_df = pd.read_excel('test.xlsx') # 将数据转换为网格格式 grid = excel_data_df.pivot(index='y', columns='x', values='z') # 确保网格按坐标顺序排列 grid = grid.sort_index().sort_index(axis=1) fig = plt.imshow(grid, extent=[excel_data_df['x'].min(), excel_data_df['x'].max(), excel_data_df['y'].min(), excel_data_df['y'].max()], origin="lower", cmap='jet') plt.scatter(excel_data_df['x'], excel_data_df['y'], 400, facecolors='none') plt.xlabel('X Values', fontsize=15) plt.ylabel('Y Values', fontsize=15) plt.title('Heatmap', fontsize=20) plt.tight_layout() plt.show()
方案2:修复interp2d的使用问题
若必须使用插值,可通过调整参数避免警告和异常区域:
import matplotlib.pyplot as plt import numpy as np from scipy.interpolate import interp2d import pandas as pd excel_data_df = pd.read_excel('test.xlsx') x_list = excel_data_df['x'].to_numpy() y_list = excel_data_df['y'].to_numpy() z_list = excel_data_df['z'].to_numpy() # 设置s参数允许微小误差,避免严格过点导致的警告 f = interp2d(x_list, y_list, z_list, kind="linear", s=1e-3) x_coords = np.arange(x_list.min(), x_list.max()+1) y_coords = np.arange(y_list.min(), y_list.max()+1) z = f(x_coords, y_coords) # 改用nearest插值,避免bicubic放大边界误差 fig = plt.imshow(z, extent=[x_list.min(), x_list.max(), y_list.min(), y_list.max()], origin="lower", interpolation='nearest', cmap='jet') plt.scatter(x_list, y_list, 400, facecolors='none') plt.xlabel('X Values', fontsize=15) plt.ylabel('Y Values', fontsize=15) plt.title('Heatmap', fontsize=20) plt.tight_layout() plt.show()
内容的提问来源于stack exchange,提问作者MJay
相关产品推荐
相关产品推荐

