You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python绘制Taylor图:为处理前后的A/B/C模型添加编号标注并消除图例重复

Solution for Taylor Diagram Labeling and Legend Cleanup

Got it, let's get your Taylor Diagram sorted out with the two features you need: numbered labels for each model and a clean, non-redundant legend. Here's the revised code with explanations of the key changes:

Revised Full Code

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.projections import PolarAxes
import mpl_toolkits.axisartist.grid_finder as gf
import mpl_toolkits.axisartist.floating_axes as fa
from matplotlib.lines import Line2D

class TaylorDiagram(object):
    def __init__(self, STD ,fig=None, rect=111, label='_'):
        self.STD = STD
        tr = PolarAxes.PolarTransform()
        # Correlation labels
        rlocs = np.concatenate(((np.arange(11.0) / 10.0), [0.95, 0.99]))
        tlocs = np.arccos(rlocs) # Conversion to polar angles
        gl1 = gf.FixedLocator(tlocs) # Positions
        tf1 = gf.DictFormatter(dict(zip(tlocs, map(str, rlocs))))
        # Standard deviation axis extent
        self.smin = 0
        self.smax = 1.6 * self.STD
        gh = fa.GridHelperCurveLinear(tr,extremes=(0,(np.pi/2),self.smin,self.smax),grid_locator1=gl1,tick_formatter1=tf1,)
        if fig is None:
            fig = plt.figure()
        ax = fa.FloatingSubplot(fig, rect, grid_helper=gh)
        fig.add_subplot(ax)
        # Angle axis
        ax.axis['top'].set_axis_direction('bottom')
        ax.axis['top'].label.set_text("Correlation coefficient")
        ax.axis['top'].toggle(ticklabels=True, label=True)
        ax.axis['top'].major_ticklabels.set_axis_direction('top')
        ax.axis['top'].label.set_axis_direction('top')
        # X axis
        ax.axis['left'].set_axis_direction('bottom')
        ax.axis['left'].label.set_text("Standard deviation")
        ax.axis['left'].toggle(ticklabels=True, label=True)
        ax.axis['left'].major_ticklabels.set_axis_direction('bottom')
        ax.axis['left'].label.set_axis_direction('bottom')
        # Y axis
        ax.axis['right'].set_axis_direction('top')
        ax.axis['right'].label.set_text("Standard deviation")
        ax.axis['right'].toggle(ticklabels=True, label=True)
        ax.axis['right'].major_ticklabels.set_axis_direction('left')
        ax.axis['right'].label.set_axis_direction('top')
        # Useless
        ax.axis['bottom'].set_visible(False)
        # Contours along standard deviations
        ax.grid()
        self._ax = ax # Graphical axes (cartesian)
        self.ax = ax.get_aux_axes(tr) # Polar coordinates
        # Add reference point and STD contour
        l , = self.ax.plot([0], self.STD, 'k*', ls='', ms=12, label=label)
        t = np.linspace(0, (np.pi / 2.0))
        r = np.zeros_like(t) + self.STD
        self.ax.plot(t, r, 'k--', label='_')
        # Collect sample points for latter use (if needed)
        self.samplePoints = [l]

    # Fixed: Removed duplicate add_sample method (original had two identical methods with same name)
    def add_sample(self, STD, corr, *args, **kwargs):
        l, = self.ax.plot(np.arccos(corr), STD, *args, **kwargs) # (theta, radius)
        self.samplePoints.append(l)
        return l

    def add_contours(self, levels=5,**kwargs):
        rs, ts = np.meshgrid(np.linspace(self.smin, self.smax), np.linspace(0, (np.pi / 2.0)))
        RMSE=np.sqrt(np.power(self.STD, 2) + np.power(rs, 2) - (2.0 * self.STD * rs *np.cos(ts)))
        contours = self.ax.contour(ts, rs, RMSE, levels, **kwargs)
        return contours

def srl(obsSTD, s, s1, r, r1, l, l1, fname):
    fig=plt.figure(figsize=(8,8))
    dia=TaylorDiagram(obsSTD, fig=fig, rect=111, label='ref')
    plt.clabel(dia.add_contours(colors='#808080'), inline=1, fontsize=10)
    
    # Plot pre-processing points (red circles) with numbered labels
    for idx, (std_val, corr_val, model_label) in enumerate(zip(s, r, l)):
        # Add the data point
        point = dia.add_sample(std_val, corr_val, marker='o', mec='red', mfc='none', mew=1.6)
        # Convert polar coordinates to cartesian for text placement
        theta = np.arccos(corr_val)
        x = std_val * np.cos(theta)
        y = std_val * np.sin(theta)
        # Add numbered label (offset slightly to avoid overlapping the marker)
        dia._ax.text(x + 0.03, y + 0.03, str(idx+1), fontsize=10, color='darkred', fontweight='bold')
    
    # Plot post-processing points (blue triangles) with numbered labels
    for idx, (std_val, corr_val, model_label) in enumerate(zip(s1, r1, l1)):
        # Add the data point
        point = dia.add_sample(std_val, corr_val, marker='^', mec='blue', mfc='none', mew=1.6)
        # Convert polar coordinates to cartesian for text placement
        theta = np.arccos(corr_val)
        x = std_val * np.cos(theta)
        y = std_val * np.sin(theta)
        # Add numbered label
        dia._ax.text(x + 0.03, y + 0.03, str(idx+1), fontsize=10, color='darkblue', fontweight='bold')
    
    # Custom legend: Avoid duplicate A/B/C entries, clearly separate pre/post processing
    custom_legend = [
        Line2D([0], [0], marker='o', color='w', mec='red', mfc='none', mew=1.6, markersize=8, label=f"处理前 (1=A, 2=B, 3=C)"),
        Line2D([0], [0], marker='^', color='w', mec='blue', mfc='none', mew=1.6, markersize=8, label=f"处理后 (1=A, 2=B, 3=C)")
    ]
    fig.legend(handles=custom_legend, numpoints=1, prop=dict(size='small'), loc=[0.7,0.3])
    
    plt.savefig(fname, dpi=150, bbox_inches='tight')
    plt.show()

# Data
obsSTD = 1
s = [1.275412605,1.391302157,1.424314937]
s1 = [0.980035327,0.997244197, 1.003002031]
r = [0.572272,0.533529,0.477572]
r1 = [0.82,0.72,0.8]
l = ['A', 'B','C']
l1 = ['A', 'B','C']
fname = 'TaylorDiagram.jpg'

# Run the function
srl(obsSTD, s, s1, r, r1, l,l1, fname)

Key Changes Explained

  1. Fixed Duplicate add_sample Method:

    • The original code had two identical add_sample methods with the same name, which meant only the second one was actually used. I merged them into a single, reusable method that works for both pre and post-processing points.
  2. Added Numbered Labels:

    • For each data point, I converted its polar coordinates (theta, radius) to Cartesian coordinates (x, y) so we can place text labels correctly on the plot.
    • Added a small offset to the label position so it doesn't overlap with the marker, and used bold, colored text to match the marker style (dark red for pre-processing, dark blue for post-processing).
  3. Cleaned Up Legend:

    • Instead of using the auto-generated legend from sample points (which caused duplicate A/B/C entries), I created custom legend entries using Line2D objects.
    • The legend clearly states which marker corresponds to pre/post processing, and explicitly maps the numbers 1/2/3 to models A/B/C, so there's no ambiguity.
  4. Minor Improvements:

    • Added plt.savefig to ensure the diagram is saved properly with tight bounding box.
    • Used fontweight='bold' for labels to make them more readable.

内容的提问来源于stack exchange,提问作者user

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 18:29:08