Skip to content

Instantly share code, notes, and snippets.

@BuckyI
Last active September 18, 2023 14:26
Show Gist options
  • Save BuckyI/750ba24671ffac1fa4f668dd7be9683a to your computer and use it in GitHub Desktop.
Save BuckyI/750ba24671ffac1fa4f668dd7be9683a to your computer and use it in GitHub Desktop.
Draw mean-difference plot

Explain

Mean-Difference plot, or Bland–Altman plot can be used to compare the prediction accuracy.

Bland and Altman drive the point that any two methods that are designed to measure the same parameter (or property) should have good correlation when a set of samples are chosen such that the property to be determined varies considerably.

This is how they looks:

01

02

03

04

The code is based on statsmodels.api but modified to change appereance. Also refer to: matplotlib - Bland-Altman plot in Python - Stack Overflow

import pandas as pd
import statsmodels.api as sm
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams
from matplotlib import font_manager
def plot(m1, m2):
# data process
means = np.mean([m1, m2], axis=0)
diffs = m1 - m2
mean_diff = np.mean(diffs)
std_diff = np.std(diffs, axis=0)
# draw
fig, ax = plt.subplots(1,figsize=(2.95,2.95), dpi=600) # 75mm/25.4=2.95磅
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.scatter(means, diffs, c='black', s=0.6) # Plot the means against the diffs.
ax.axhline(mean_diff, color='gray', linewidth=1, linestyle='--') # draw mean line.
# Annotate mean line with mean difference.
ax.annotate('mean diff:\n{}'.format(np.round(mean_diff, 2)),
xy=(0.99, 0.5),
horizontalalignment='right',
verticalalignment='center',
fontsize=7.5, # !!!
xycoords='axes fraction')
sd_limit=1.96
half_ylim = (1.5 * sd_limit) * std_diff
ax.set_ylim(mean_diff - half_ylim, mean_diff + half_ylim) # 对称
limit_of_agreement = sd_limit * std_diff
lower = mean_diff - limit_of_agreement
upper = mean_diff + limit_of_agreement
for j, lim in enumerate([lower, upper]):
ax.axhline(lim, color='gray', linewidth=1, linestyle=':')
ax.annotate(f'-{sd_limit} SD: {lower:0.2g}',
xy=(0.99, 0.07),
horizontalalignment='right',
verticalalignment='bottom',
fontsize=7.5, # !!!
xycoords='axes fraction')
ax.annotate(f'+{sd_limit} SD: {upper:0.2g}',
xy=(0.99, 0.92),
horizontalalignment='right',
fontsize=7.5, # !!!
xycoords='axes fraction')
ax.set_xlabel('Mean of predicted and measured VO2\n($L×min^{-1}×kg^{-1}$)',fontsize=7.5)
ax.set_ylabel('Difference of predicted and measured VO2\n($L×min^{-1}×kg^{-1}$)',fontsize=7.5)
ax.tick_params(labelsize=7.5)
fig.tight_layout()
return ax
# data load
data = pd.read_csv("/content/Nanjing01_Plain.csv")
m1, m2 = data['y_true']/1000, data['y_pred']/1000
ax = plot(m1, m2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment