如何修改Taylor图轴范围至-1~1并添加象限展示负相关
解决easy_mpl绘制Taylor图无法展示负相关模型的问题
问题背景
使用easy_mpl库的taylor_plot函数绘制Taylor图时,Model-7和Model-8未在图中显示,推测是这两个模型与观测值的相关系数为负,超出了默认Taylor图仅展示第一象限(相关系数01)的范围。需要修改绘图逻辑,让Taylor图支持-11的全范围相关系数,展示所有象限的点。
解决方案
由于easy_mpl的taylor_plot默认不支持负相关展示,我们可以手动计算模型的统计量,使用matplotlib自定义绘制支持全相关系数范围的Taylor图,实现类似R语言的效果。
步骤1:计算模型统计量
首先读取数据,计算每个模型的标准差、与观测值的相关系数,以及偏差:
import numpy as np import matplotlib.pyplot as plt from matplotlib.patches import Circle # 数据样本 data = np.array([[2.614, 0.282, 0.901, 0.254, 0.42, 0.785, 0.4871, 0.6842, 1.0216], [3.141, 0.265, 0.717, 0.245, 0.46, 0.6122, 0.5516, 0.6457, 0.5939], [0.563, 0.282, 0.661, 0.252, 1.81, 0.636, 0.4983, 0.6041, 0.5376], [2.343, 0.292, 0.563, 0.289, 0.6, 0.4559, 0.515, 0.4323, 0.65], [0.893, 0.276, 0.538, 0.248, 0.37, 0.3996, 0.4455, 0.3962, 0.5438], [0.426, 0.253, 0.637, 0.248, 0.42, 0.5251, 0.4136, 0.4809, 0.5804], [8.563, 0.39, 1.192, 0.308, 0.61, 1.0787, 1.1276, 0.8346, 0.5782], [2.213, 0.499, 1.587, 0.279, 0.88, 1.2618, 1.6147, 1.1937, 1.0943], [3.065, 1.728, 1.728, 4.059, 1.1, 1.4816, 1.5246, 1.275, 3.4991], [9.223, 2.045, 2.045, 8.701, 0.86, 2.1728, 4.8029, 2.3691, 0.9047]]) observations = data[:, 0] simulations = {"Model-1": data[:, 1], "Model-2": data[:, 2], "Model-3": data[:, 3], "Model-4": data[:, 4], "Model-5": data[:,5], "Model-6": data[:,6], "Model-7": data[:,7], "Model-8": data[:,8]} # 计算观测值标准差 obs_std = np.std(observations, ddof=1) # 计算每个模型的统计量:标准差、相关系数、偏差 model_stats = {} for name, sim_data in simulations.items(): sim_std = np.std(sim_data, ddof=1) corr_coef = np.corrcoef(observations, sim_data)[0, 1] bias = np.mean(sim_data) - np.mean(observations) model_stats[name] = (sim_std, corr_coef, bias)
步骤2:自定义绘制全范围Taylor图
使用matplotlib的极坐标系统,极角对应相关系数(r = cos(theta)),极径对应标准差,绘制支持-1~1相关系数的Taylor图:
# 创建极坐标画布 fig, ax = plt.subplots(figsize=(8, 8), subplot_kw={'projection': 'polar'}) # 设置极角范围:0到π,对应相关系数1到-1 ax.set_theta_range(0, np.pi) # 设置极角刻度,直接显示相关系数值 ax.set_xticks([0, np.pi/4, np.pi/2, 3*np.pi/4, np.pi]) ax.set_xticklabels(['1', '0.5', '0', '-0.5', '-1']) # 设置径向轴(标准差)范围,取所有标准差最大值的1.1倍 max_std = max([stat[0] for stat in model_stats.values()] + [obs_std]) ax.set_ylim(0, max_std * 1.1) ax.set_ylabel('Standard Deviation', labelpad=20) # 绘制观测值标记(红色星号) ax.scatter(0, obs_std, marker='*', s=200, color='red', zorder=10, label='观测值') # 添加等相关系数的虚线射线 for corr_val in [-1, -0.5, 0, 0.5, 1]: theta = np.arccos(corr_val) ax.plot([theta, theta], [0, max_std*1.1], color='#1A74A5', linestyle='--', linewidth=1.5) # 添加等标准差的同心圆 for std_level in np.linspace(0, max_std*1.1, 5): circle = Circle((0, 0), std_level, transform=ax.transData._b, color='#5CB994', linestyle='dotted', linewidth=2.0, fill=False) ax.add_artist(circle) # 绘制每个模型的点,并标注偏差 colors = plt.cm.tab10(np.arange(len(model_stats))) for (model_name, (sim_std, corr, bias)), color in zip(model_stats.items(), colors): theta = np.arccos(corr) ax.scatter(theta, sim_std, s=100, edgecolor='black', linewidth=1.0, color=color, label=model_name) # 标注偏差值 ax.text(theta, sim_std + max_std*0.02, f'偏差: {bias:.2f}', ha='center', va='bottom') # 添加图例和标题 ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1.1)) ax.set_title('Taylor 图', y=1.1) plt.show()
说明
- 手动计算统计量绕开了easy_mpl的限制,确保所有模型(包括负相关的)都能展示
- 极坐标的角度与相关系数通过
theta = arccos(corr)转换,覆盖-1到1的全范围 - 保留了原代码中的样式配置(颜色、线宽等),同时添加了偏差标注
内容的提问来源于stack exchange,提问作者asheef_ik
相关产品推荐
相关产品推荐

