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
Fixed Duplicate
add_sampleMethod:- The original code had two identical
add_samplemethods 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.
- The original code had two identical
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).
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
Line2Dobjects. - 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.
- Instead of using the auto-generated legend from sample points (which caused duplicate A/B/C entries), I created custom legend entries using
Minor Improvements:
- Added
plt.savefigto ensure the diagram is saved properly with tight bounding box. - Used
fontweight='bold'for labels to make them more readable.
- Added
内容的提问来源于stack exchange,提问作者user
相关产品推荐
相关产品推荐

