Апостериорный тест для непараметрических и небольших наборов данных

Вопрос или проблема

В лаборатории, в которой я работаю, мы провели эксперимент, чтобы наблюдать, эффективны ли цианобактерии в изменениях концентрации силикатов в озере. Эксперимент имел 3 различные переменные:

  • тип организма
  • было ли добавлено силиката в растворе
  • тип бульона (только вода из озера Салда или вода из озера Салда, смешанная с бульоном).

Были два повторения для каждой комбинации переменных, в результате чего в эксперименте было 22 образца. Мы проводили наблюдения под микроскопом и измеряли концентрации Mg и Ca для каждого образца (18 ненулевых концентраций).

Я выполнил permutation Kruskal-Wallis тест, чтобы выяснить, можем ли мы получить какую-либо информацию о том, имел ли какой-либо из упомянутых выше факторов значительное влияние на концентрации Mg или Ca. Я провел тест по категориям: тип организма, добавление силиката и тип бульона, и выяснил, что тип организма в растворах был значимым для обоих Mg и Ca, но остальные категории не имели значительных различий.

Когда я выполнил пост-хок тест, используя тест Данна (с поправкой Холма), результаты были похожими, но это не показало значимости для типа организма для Ca. Однако я затем узнал, что из-за размера моей выборки версия теста Данна с permutation может быть более подходящей. Так как я не знаю, как выполнить permutation версию теста Данна (снова с поправкой Холма), я получил предложение кода от Copilot. Однако на этот раз результаты показали значительное различие в типе бульона. Естественно, теперь я рассматриваю, не было ли это ошибкой в коде или один из тестов имел ошибку типа I или типа II. Если с кодом нет проблем, я думаю о проведении теста на размер эффекта. Вы можете найти мой код ниже. Я был бы признателен за любые предложения.

P.S. Я также могу предоставить свой код для permutation Kruskal-Wallis, если это может быть необходимо

# Определение функции permutation
def perm_dunn(data, dv, between, n_perm = 10000, random_state = 42):
    """
    Выполняет permutation тест Данна на данном DataFrame.

    Параметры:
    - data: pandas DataFrame с данными.
    - dv: Название столбца зависимой переменной (например, 'Mg' или 'Ca').
    - between: Название столбца с категорией группировки.
    - n_perm: Количество permutation выполняемых тестов.
    - random_state: Начальное значение для воспроизводимости.

    Возвращает:
    - result: pandas DataFrame с наблюдаемой разницей, p-значением и поправкой Холма.

    Исключения:
    - Вызывает исключение, если зависимая переменная не является числовой.
    - Вызывает исключение, если переменная группировки не является категориальной.
    """
    # Проверка, является ли зависимая переменная числовой
    if data[dv].dtype not in ['int64', 'float64']:
        raise ValueError('Зависимая переменная должна быть числовой.')

    # Проверка, является ли переменная группировки категориальной
    if data[between].dtype not in ['object', 'category']:
        raise ValueError('Переменная группировки должна быть категориальной.')

    groups = data[between].unique()
    result = {}

    for (group1, group2) in it.combinations(groups, 2):
        data1 = data[data[between] == group1][dv].values
        data2 = data[data[between] == group2][dv].values
        observed_diff = np.abs(np.mean(data1) - np.mean(data2))

        cmb = np.concatenate([data1, data2])
        perm_diffs = []
        np.random.seed(random_state)
        for _ in range(n_perm):
            np.random.shuffle(cmb)
            perm_data1 = cmb[:len(data1)]
            perm_data2 = cmb[len(data1):]
            perm_diffs.append(np.abs(np.mean(perm_data1) - np.mean(perm_data2)))

        perm_diffs = np.array(perm_diffs)
        p_value = np.sum(perm_diffs >= observed_diff) / n_perm
        result[(group1, group2)] = [observed_diff, p_value]
        # Сохраните названия групп в виде строк в словаре результатов
        result[(group1, group2)].extend([str(group1), str(group2)])

    # Применение поправки Холма
    p_values = [value[1] for value in result.values()]
    reject, p_values_corr, _, _ = smt.multipletests(p_values, method = 'holm')
    for i, key in enumerate(result.keys()):
        result[key].append(p_values_corr[i])

    # Создание DataFrame из результатов
    result = pd.DataFrame(result).T
    result.columns = ['Observed Difference', 'p-value', 'Group 1', 'Group 2', 'Holm Correction']
    # Упорядочить столбцы по Group 1, Group 2, Observed Difference, p-value, Holm Correction
    result = result[['Group 1', 'Group 2', 'Observed Difference', 'p-value', 'Holm Correction']]

    return result

# Выполнить permutation тест Данна для каждого столбца для Mg и Ca соответственно, используя цикл for
perm_dunn_mg = pd.DataFrame()
perm_dunn_ca = pd.DataFrame()

for col_name in cyano[['Shape', 'Silica', 'Broth']]:
    perm_dunn_mg = perm_dunn_mg._append(perm_dunn(data = cyano.drop(columns = ["SampleName", "Replicate"]), dv = 'Mg', between = col_name), ignore_index = True)
    perm_dunn_ca = perm_dunn_ca._append(perm_dunn(data = cyano.drop(columns = ["SampleName", "Replicate"]), dv = 'Ca', between = col_name), ignore_index = True)

# Напечатать результаты
print(perm_dunn_mg)
print(perm_dunn_ca)
```

Ответ или решение

В свете вашего вопроса о пост-хок тесте для непараметрических и малых выборок, давайте подробно рассмотрим ситуацию.

Теория

При анализе данных из экспериментов, где распределение может не соответствовать нормальному, часто прибегают к использованию непараметрических тестов, таких как критерий Краскела-Уоллиса. Этот тест, будучи аналогом однофакторного дисперсионного анализа (ANOVA), позволяет оценить, есть ли статистически значимые различия между группами. Однако, когда наблюдается значимый результат, требуется применить пост-хок тест, чтобы определить, какие именно группы различаются.

Для непараметрических данных с малыми объёмами выборок, традиционный тест Данна с поправкой на множественные сравнения, например, по методу Холма, может быть не всегда уместен из-за ограничений в точности при малых выборках. В таком случае рекомендуется применять пермутационные версии этих тестов, которые более устойчивы к специфике малых данных и менее зависят от предположений о распределении данных.

Пример

В вашем случае вы анализировали данные об изменении концентраций Mg и Ca под воздействием различных факторов в экспериментах с цианобактериями. Первоначальные результаты теста Краскела-Уоллиса показали, что тип организма существенно влияет на концентрацию обоих элементов. Однако пост-хок тест Данна (с коррекцией Holm) выявил значимость отличий только для Mg. После применения пермутационного варианта теста Данна результат изменился: показалась значимость не только для типа организма, но и для типа бульона. Это предполагает возможные ошибки типов I или II в одном из тестов, что актуально для подобных малых наборов данных.

Применение

Ваш код для пермутационного теста Данна реализован достаточно полно и позволяет выполнять необходимые вычисления. Тем не менее, для уверенности в корректности результата полезно было бы удостовериться в корректности процесса пермутации и вычисления p-значений. Имейте в виду, что любые ошибки в комментариях (например, отсутствие логического оператора в выражении np.sum(perm_diffs >= observed_diff)) могут привести к неправильной интерпретации данных. Верно будет использовать np.sum(perm_diffs >= observed_diff) в контексте Python.

Для дополнительных рекомендаций:

  1. Проверка кода: Пересмотрите зависимости и требования к данным. Убедитесь, что данные однородны и качественно организованы, чтобы избежать систематических ошибок.
  2. Анализ мощности теста: Проведите анализ мощности, чтобы оценить вероятность обнаружения настоящих эффектов при данных характеристиках выборки. Это помогает понять, не является ли отсутствие значимости результатом недостаточной статистической мощности.
  3. Эффект размера: Как и планировали, расчёт эффектов значимости даст вам дополнительное понимание того, насколько сила выявленных различий велика и имеет ли она практическую значимость.

Последний момент: в выборе подходящих статистических методов всегда учитывайте специфику вашей проблемы и экспериментальных данных. Достаточная научная обоснованность методов и инструментов анализа является ключом к достоверным результатам и правильным научным выводам.

Оцените материал
Добавить комментарий

Капча загружается...