Comparación de métodos#
Supongamos que para un tipo específico de medición, existen dos métodos para realizarla. Una pregunta común en este contexto es si ambos métodos podrían reemplazarse entre sí. Por lo tanto, se investiga la similitud de las mediciones. Un método para esto es el análisis de Bland-Altman, llamado así por Martin Bland y Douglas Altman.
Ver también Altman and Bland: Measurement in Medicine: the Analysis of Method Comparison Studies
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
Antes de sumergirnos en el análisis de Bland-Altman, echemos un vistazo a métodos directos para comparar métodos. Una suposición importante es que trabajamos con datos emparejados. Esto significa que podemos aplicar los dos métodos de medición a la misma muestra sin destruirla y sin que los dos métodos se perjudiquen entre sí.
# make up some data
measurement_A = [1, 9, 7, 1, 2, 8, 9, 2, 1, 7, 8]
measurement_B = [4, 5, 5, 7, 4, 5, 4, 6, 6, 5, 4]
# show measurements as table
pd.DataFrame([measurement_A, measurement_B], ["A", "B"]).transpose()
| A | B | |
|---|---|---|
| 0 | 1 | 4 |
| 1 | 9 | 5 |
| 2 | 7 | 5 |
| 3 | 1 | 7 |
| 4 | 2 | 4 |
| 5 | 8 | 5 |
| 6 | 9 | 4 |
| 7 | 2 | 6 |
| 8 | 1 | 6 |
| 9 | 7 | 5 |
| 10 | 8 | 4 |
Comparación de medias#
Un método muy simple para comparar matrices de mediciones es comparar sus medias.
print("Mean(A) = " + str(np.mean(measurement_A)))
print("Mean(B) = " + str(np.mean(measurement_B)))
Mean(A) = 5.0
Mean(B) = 5.0
Usando este método, se podría concluir que ambos métodos proporcionan mediciones similares porque su media es igual. Sin embargo, esto podría ser engañoso.
Gráficos de dispersión#
Un método más visual para la comparación de métodos es dibujar gráficos de dispersión. En estos gráficos, las mediciones de un método se trazan contra el otro método.
plt.plot(measurement_A, measurement_B, "*")
plt.plot([0, 10], [0, 10])
plt.axis([0, 10, 0, 10])
plt.xlabel('measurement A')
plt.ylabel('measurement B')
plt.show()
Obviamente, A y B conducen a resultados bastante diferentes. Si los puntos azules estuvieran en la línea naranja, concluiríamos que las mediciones están relacionadas.
Histogramas#
Como ya concluimos que ambas mediciones se encuentran en rangos diferentes, deberíamos echar un vistazo a la distribución. Los histogramas son una buena opción de gráfico. Para asegurarnos de que los histogramas para ambas mediciones se visualicen igual, por ejemplo, con el mismo rango en el eje x, podemos escribir nuestra propia pequeña función draw_histogram:
def draw_histogram(data):
counts, bins = np.histogram(data, bins=10, range=(0,10))
plt.hist(bins[:-1], bins, weights=counts)
plt.axis([0, 10, 0, 4])
plt.show()
draw_histogram(measurement_A)
draw_histogram(measurement_B)
Correlación#
Para medir la relación entre dos mediciones, podemos tomar la definición de Pearson del coeficiente de correlación
Los datos para el siguiente experimento se toman de Altman & Bland, The Statistician 32, 1983, Fig. 1.
# new measurements
measurement_1 = [130, 132, 138, 145, 148, 150, 155, 160, 161, 170, 175, 178, 182, 182, 188, 195, 195, 200, 200, 204, 210, 210, 215, 220, 200]
measurement_2 = [122, 130, 135, 132, 140, 151, 145, 150, 160, 150, 160, 179, 168, 175, 187, 170, 182, 179, 195, 190, 180, 195, 210, 190, 200]
# scatter plot
plt.plot(measurement_1, measurement_2, "o")
plt.plot([120, 220], [120, 220])
plt.axis([120, 220, 120, 220])
plt.show()
# Determining Pearson's correlation coefficient r with a for-loop
import numpy as np
# get the mean of the measurements
mean_1 = np.mean(measurement_1)
mean_2 = np.mean(measurement_2)
# get the number of measurements
n = len(measurement_1)
# get the standard deviation of the measurements
std_dev_1 = np.std(measurement_1)
std_dev_2 = np.std(measurement_2)
# sum the expectation of
sum = 0
for m_1, m_2 in zip(measurement_1, measurement_2):
sum = sum + (m_1 - mean_1) * (m_2 - mean_2) / n
r = sum / (std_dev_1 * std_dev_2)
print ("r = " + str(r))
r = 0.9435300113035253
# Determine Pearson's r using scipy
from scipy import stats
stats.pearsonr(measurement_1, measurement_2)[0]
0.9435300113035257
Gráficos de Bland-Altman#
Los gráficos de Bland-Altman son una forma de visualizar específicamente las diferencias entre mediciones emparejadas. Al buscar en Google código Python que dibuje tales gráficos, uno puede terminar con esta solución:
# A function for drawing Bland-Altman plots
# source https://stackoverflow.com/questions/16399279/bland-altman-plot-in-python
import matplotlib.pyplot as plt
import numpy as np
def bland_altman_plot(data1, data2, *args, **kwargs):
data1 = np.asarray(data1)
data2 = np.asarray(data2)
mean = np.mean([data1, data2], axis=0)
diff = data1 - data2 # Difference between data1 and data2
md = np.mean(diff) # Mean of the difference
sd = np.std(diff, axis=0) # Standard deviation of the difference
plt.scatter(mean, diff, *args, **kwargs)
plt.axhline(md, color='gray', linestyle='--')
plt.axhline(md + 1.96*sd, color='gray', linestyle='--')
plt.axhline(md - 1.96*sd, color='gray', linestyle='--')
plt.xlabel("Average")
plt.ylabel("Difference")
# draw a Bland-Altman plot
bland_altman_plot(measurement_1, measurement_2)
plt.show()
Ejercicio#
Procese nuevamente el conjunto de datos de plátanos, por ejemplo, usando un bucle for que recorra la carpeta ../data/banana/, y procese todas las imágenes. Mida el tamaño de las rodajas de plátano utilizando los métodos de umbralización de scikit-image threshold_otsu y threshold_yen. Compare ambos métodos utilizando las técnicas que aprendió anteriormente.