To create a Taylor diagram in Python for comparing five models against observations, you can use the skill_metrics
or taylorDiagram
implementations from various libraries. Hereโs a step-by-step using Matplotlib and SkillMetrics, which is commonly used in the geoscience community.
numpy
, matplotlib
, and optionally, skill_metrics
.Below is a custom implementation using only matplotlib
.
import matplotlib.pyplot as plt
import numpy as np
# Example data
obs = np.array([3.0, 3.5, 4.0, 4.5, 5.0]) # observed values
models = {
'Model A': np.array([2.8, 3.4, 4.2, 4.7, 4.9]),
'Model B': np.array([3.2, 3.6, 4.1, 4.4, 5.1]),
'Model C': np.array([2.9, 3.2, 4.0, 4.3, 4.8]),
'Model D': np.array([3.0, 3.7, 3.9, 4.6, 5.0]),
'Model E': np.array([3.1, 3.5, 4.3, 4.5, 5.2]),
}
# Compute statistics
def compute_stats(model, obs):
std_model = np.std(model)
std_obs = np.std(obs)
corr_coeff = np.corrcoef(model, obs)[0, 1]
return std_model, corr_coeff
# Setup Taylor diagram
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, polar=True)
ax.set_theta_direction(-1)
ax.set_theta_offset(np.pi / 2)
# Reference STD
std_ref = np.std(obs)
ax.plot([0], [std_ref], 'ko', label='Observation')
# Grid and labels
rs = np.linspace(0, 1.5 * std_ref, 100)
ts = np.arccos(np.linspace(0, 1, 100))
for r in rs[::20]:
ax.plot(ts, np.full_like(ts, r), color='gray', alpha=0.3)
# Plot each model
colors = ['r', 'g', 'b', 'm', 'c']
for i, (name, model_data) in enumerate(models.items()):
std_model, corr = compute_stats(model_data, obs)
theta = np.arccos(corr)
ax.plot(theta, std_model, 'o', label=name, color=colors[i])
ax.set_title('Taylor Diagram')
ax.set_rlim(0, 1.5 * std_ref)
ax.set_rlabel_position(135)
ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1.1))
plt.tight_layout()
plt.show()
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
df = pd.read_excel("test_data.xlsx")
# Separate observed and model data
obs = df['Observed']
models = df.drop(columns='Observed')
# Compute statistics
def compute_stats(model, obs):
std_model = np.std(model)
corr_coeff = np.corrcoef(model, obs)[0, 1]
return std_model, corr_coeff
# Setup Taylor diagram
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, polar=True)
ax.set_theta_direction(-1)
ax.set_theta_offset(np.pi / 2)
# Reference STD
std_ref = np.std(obs)
ax.plot([0], [std_ref], 'ko', label='Observation')
# Grid and labels
rs = np.linspace(0, 1.5 * std_ref, 100)
ts = np.arccos(np.linspace(0, 1, 100))
for r in rs[::20]:
ax.plot(ts, np.full_like(ts, r), color='gray', alpha=0.3)
# Plot each model
colors = ['r', 'g', 'b', 'm', 'c']
for i, column in enumerate(models.columns):
model_data = models[column].values
std_model, corr = compute_stats(model_data, obs)
theta = np.arccos(corr)
ax.plot(theta, std_model, 'o', label=column, color=colors[i % len(colors)])
ax.set_title('Model 1 - Test',pad=30)
ax.set_rlim(0, 1.5 * std_ref)
ax.set_rlabel_position(135)
ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1.1))
plt.tight_layout()
plt.show()
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
pandas
: for reading and handling tabular data from Excel.matplotlib.pyplot
: for creating the polar plot (Taylor diagram).numpy
: for numerical operations like standard deviation and correlation.df = pd.read_excel("test_data.xlsx")
test_data.xlsx
into a DataFrame named df
.obs = df['Observed']
models = df.drop(columns='Observed')
obs
: the column containing the observed/reference data.models
: all other columns, each assumed to be output from a different model.def compute_stats(model, obs):
std_model = np.std(model)
corr_coeff = np.corrcoef(model, obs)[0, 1]
return std_model, corr_coeff
Calculates:
std_model
: standard deviation of the modelโs predictions.corr_coeff
: correlation coefficient between the model and observations.fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, polar=True)
ax.set_theta_direction(-1)
ax.set_theta_offset(np.pi / 2)
set_theta_direction(-1)
: clockwise direction.set_theta_offset(np.pi / 2)
: sets 0ยฐ (correlation = 1) to the top of the plot.std_ref = np.std(obs)
ax.plot([0], [std_ref], 'ko', label='Observation')
std_ref
.rs = np.linspace(0, 1.5 * std_ref, 100)
ts = np.arccos(np.linspace(0, 1, 100))
for r in rs[::20]:
ax.plot(ts, np.full_like(ts, r), color='gray', alpha=0.3)
rs
: radial distances.ts
: angular values converted from correlation.colors = ['r', 'g', 'b', 'm', 'c']
for i, column in enumerate(models.columns):
model_data = models[column].values
std_model, corr = compute_stats(model_data, obs)
theta = np.arccos(corr)
ax.plot(theta, std_model, 'o', label=column, color=colors[i % len(colors)])
Loops through each model column:
theta
).ax.set_title('Model 1 - Test', pad=30)
pad
.ax.set_rlim(0, 1.5 * std_ref)
ax.set_rlabel_position(135)
ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1.1))
plt.tight_layout()
plt.show()
This code reads observed and model data from Excel and uses a Taylor diagram to compare models based on: