Тест тау Кендалла#

Тау Кендалла — это мера соответствия между двумя ранжировками.

Рассмотрим следующие данные из [1], который изучал взаимосвязь между свободным пролином (аминокислотой) и общим коллагеном (белком, часто встречающимся в соединительной ткани) в больной человеческой печени.

The x и y массивы ниже записывают измерения двух соединений. Наблюдения парные: каждое измерение свободного пролина было взято из той же печени, что и измерение общего коллагена с тем же индексом.

import numpy as np
# total collagen (mg/g dry weight of liver)
x = np.array([7.1, 7.1, 7.2, 8.3, 9.4, 10.5, 11.4])
# free proline (μ mole/g dry weight of liver)
y = np.array([2.8, 2.9, 2.8, 2.6, 3.5, 4.6, 5.0])

Эти данные были проанализированы в [2] используя коэффициент корреляции Спирмена, статистику, похожую на тау Кендалла, поскольку она также чувствительна к порядковой корреляции между выборками. Проведём аналогичное исследование с использованием Kendall's tau.

from scipy import stats
res = stats.kendalltau(x, y)
res.statistic
np.float64(0.5499999999999999)

Значение этой статистики стремится быть высоким (близким к 1) для выборок с сильно положительной порядковой корреляцией, низким (близким к -1) для выборок с сильно отрицательной порядковой корреляцией и малым по величине (близким к нулю) для выборок со слабой порядковой корреляцией.

Тест выполняется путем сравнения наблюдаемого значения статистики с нулевым распределением: распределением значений статистики, полученных при нулевой гипотезе о том, что измерения общего коллагена и свободного пролина независимы.

Для этого теста нулевое распределение для больших выборок без связей аппроксимируется нормальным распределением с дисперсией (2*(2*n + 5))/(9*n*(n - 1)), где n = len(x).

import matplotlib.pyplot as plt
n = len(x)  # len(x) == len(y)
var = (2*(2*n + 5))/(9*n*(n - 1))
dist = stats.norm(scale=np.sqrt(var))
z_vals = np.linspace(-1.25, 1.25, 100)
pdf = dist.pdf(z_vals)
fig, ax = plt.subplots(figsize=(8, 5))

def plot(ax):  # we'll reuse this
    ax.plot(z_vals, pdf)
    ax.set_title("Kendall Tau Test Null Distribution")
    ax.set_xlabel("statistic")
    ax.set_ylabel("probability density")

plot(ax)
plt.show()
../../_images/64570e47da3f2061f1ab011949fe772fd15d4cbd0099fd1dc15b222fb02f8efc.png

Сравнение количественно оценивается p-значением: долей значений в нулевом распределении, столь же экстремальных или более экстремальных, чем наблюдаемое значение статистики. В двустороннем тесте, в котором статистика положительна, элементы нулевого распределения больше преобразованной статистики и элементы нулевого распределения меньше отрицательного наблюдаемой статистики оба считаются "более экстремальными".

fig, ax = plt.subplots(figsize=(8, 5))
plot(ax)
pvalue = dist.cdf(-res.statistic) + dist.sf(res.statistic)
annotation = (f'p-value={pvalue:.4f}\n(shaded area)')
props = dict(facecolor='black', width=1, headwidth=5, headlength=8)
_ = ax.annotate(annotation, (0.65, 0.15), (0.8, 0.3), arrowprops=props)
i = z_vals >= res.statistic
ax.fill_between(z_vals[i], y1=0, y2=pdf[i], color='C0')
i = z_vals <= -res.statistic
ax.fill_between(z_vals[i], y1=0, y2=pdf[i], color='C0')
ax.set_xlim(-1.25, 1.25)
ax.set_ylim(0, 0.5)
plt.show()
../../_images/60bec0811595bc6f32694bb507fffe90fe93390f9a7378de29682934220c1188.png
res.pvalue
np.float64(0.09108705741631495)

Обратите внимание, что есть небольшое расхождение между затенённой областью кривой и p-значением, возвращаемым scipy.stats.kendalltau. Это происходит потому, что наши данные имеют связи, и мы пренебрегли поправкой на связи к дисперсии нулевого распределения, которая scipy.stats.kendalltau выполняет. Для выборок без совпадений затенённые области нашего графика и p-значение, возвращаемое scipy.stats.kendalltau будет точно совпадать.

Если p-значение «маленькое» — то есть если существует низкая вероятность выборки данных из независимых распределений, которые дают такое экстремальное значение статистики — это может рассматриваться как свидетельство против нулевой гипотезы в пользу альтернативной: распределение общего коллагена и свободного пролина не независимы. Обратите внимание, что:

  • Обратное неверно; то есть тест не используется для предоставления доказательств в пользу нулевой гипотезы.

  • Порог для значений, которые будут считаться «малыми», — это выбор, который следует сделать до анализа данных [3] с учетом рисков как ложноположительных (ошибочное отклонение нулевой гипотезы), так и ложноотрицательных (неспособность отклонить ложную нулевую гипотезу).

  • Маленькие p-значения не являются доказательством большой эффект; скорее, они могут только предоставить доказательства «значимого» эффекта, означающего, что они маловероятны при нулевой гипотезе.

Для выборок без связей умеренного размера, scipy.stats.kendalltau может точно вычислить p-значение. Однако при наличии связей, scipy.stats.kendalltau прибегает к асимптотическому приближению. Тем не менее, мы можем использовать перестановочный тест для точного вычисления нулевого распределения: В соответствии с нулевой гипотезой о независимости общего коллагена и свободного пролина, каждое измерение свободного пролина было одинаково вероятно наблюдаться с любым из измерений общего коллагена. Поэтому мы можем сформировать точный нулевое распределение путем вычисления статистики для каждой возможной пары элементов между x и y.

def statistic(x):  # explore all possible pairings by permuting `x`
    return stats.kendalltau(x, y).statistic  # ignore pvalue
ref = stats.permutation_test((x,), statistic,
                             permutation_type='pairings')
fig, ax = plt.subplots(figsize=(8, 5))
plot(ax)
bins = np.linspace(-1.25, 1.25, 25)
ax.hist(ref.null_distribution, bins=bins, density=True)
ax.legend(['asymptotic approximation\n(many observations)',
           'exact null distribution'])
plot(ax)
plt.show()
../../_images/291b381df7c1a776714abcf62be2f992c8baf215dd35a2fae4d2fe29712e2085.png
ref.pvalue
np.float64(0.12222222222222222)

Обратите внимание, что существует значительное расхождение между точным p-значением, вычисленным здесь, и аппроксимацией, возвращаемой scipy.stats.kendalltau выше. Для малых выборок со связями рассмотрите выполнение перестановочного теста для более точных результатов.

Ссылки#