基于Matplotlib绘制棒球投球数据50%好球带等高线图问题求助
问题排查
你现有代码的错误主要集中在3个位置:
- 直接使用原始散点坐标生成网格:
np.meshgrid(df2_array[:,0], df2_array[:,1])会生成10000×10000的超大冗余网格,且原始散点无序、存在大量重复值,会导致插值结果混乱 - 未明确指定等高线阈值:
levels=2是将插值后的Z值范围自动均分2段生成等高线,不会固定对应你需要的50%好球概率(Z=0.5)边界 - 二元离散值直接用线性插值容易出现边界空值,对于这类概率类的等高线绘制,也可以先做二维分箱统计好球概率再画图,结果更稳定
修正后代码
import numpy as np import matplotlib.pyplot as plt from scipy.interpolate import griddata df2_array = df2[['plate_x', 'plate_z', 'strike']].to_numpy() x = df2_array[:, 0] y = df2_array[:, 1] z = df2_array[:, 2] # 1. 生成规整的等间隔网格,步长可根据你的坐标范围调整 xi = np.linspace(x.min(), x.max(), 100) yi = np.linspace(y.min(), y.max(), 100) X, Y = np.meshgrid(xi, yi) # 2. 插值得到网格点的好球概率,可选method='nearest'/'cubic'避免边界NaN Z = griddata((x, y), z, (X, Y), method='cubic') # 可选:填补边界的NaN值 Z = np.nan_to_num(Z, nan=np.nanmean(z)) # 3. 明确指定仅绘制Z=0.5的等高线,即50%好球概率边界 plt.contour(X, Y, Z, levels=[0.5], alpha=0.5, colors='red') # 如果需要同时显示热图可以加这行 # plt.contourf(X, Y, Z, cmap='RdBu', alpha=0.3) plt.xlabel('plate_x') plt.ylabel('plate_z') plt.show()
可选优化方案
如果希望结果更符合实际比赛的好球带统计规律,可以先做二维分箱计算平均好球率再画图,避免插值带来的平滑偏差:
# 二维分箱统计 H, xedges, yedges = np.histogram2d(x, y, bins=50, weights=z) counts, _, _ = np.histogram2d(x, y, bins=50) # 计算每个分箱的好球概率,避免除以0 Z_prob = np.divide(H, counts, out=np.zeros_like(H), where=counts!=0) # 取分箱中点做网格 X_bin, Y_bin = np.meshgrid((xedges[:-1] + xedges[1:])/2, (yedges[:-1] + yedges[1:])/2) plt.contour(X_bin, Y_bin, Z_prob.T, levels=[0.5], alpha=0.5)
内容的提问来源于stack exchange,提问作者JohnB
相关产品推荐
相关产品推荐

