Проблема с использованием ttest_ind в фрейме данных pandas

В настоящее время я работаю с фреймворком данных в форме:

import pandas as pd
import numpy as np
df = pd.DataFrame([['A', 12.1, 11.4, 15.1, 9.9], ['B', 8.3, 10.3, 16.6, 7.8], ['B', 7.8, 11.1, 16.3, 8.4], 
                   ['B', 8.6, 10.9, 16.4, 8.1], ['A', 12.25, 11.6, 16.25, 8.9], ['B', 8.13, 11.6, 16.7, 7.4]
                  ], columns = ['Symbol', 'C1','C2', 'C3', 'C4'])

И список списков, который включает сравнения столбцов, которые я хотел бы сделать:

lst = [['C1','C2'], ['C1','C3'], ['C3','C4']]

Я пытаюсь рассчитать разницу средних (повторяющихся символов) для каждого сравнения, а также выполнить ttest_ind, а затем вернуть новый фрейм данных с результатами, которые будут выглядеть так:

df2 = pd.DataFrame([['A', 0.675, 'pval here', -3.5, 'pval here',6.275,'pval here'], 
                    ['B', -2.7675, 'pval here', -8.2925, 'pval here', 8.575 , 'pval here']], 
                   columns = ['Symbol', 'C1-C2','C1-C2 pval', 'C1-C3', 'C1-C3 pval', 'C3-C4','C3-C4 pval'])

Найти разницу между средними значениями довольно просто, используя groupby, чтобы получить средние значения, а затем перебрать пары списка следующим образом:

df = df.groupby('Symbol').agg(np.mean)
for pair in lst:
    df[pair[0]+'-'+pair[1]] = df[pair[0]] - df[pair[1]]

Но я застрял в применении ttest_ind, а затем возвращал p-vaule в другой столбец.

Любая помощь приветствуется.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
348
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Для этого можно использовать метод scipy.stats.ttest_ind.

Метод возвращает кортеж с (t-statistic, p-value). Таким образом, мы можем получить доступ к p-value с индексом 1 следующим образом:

# Dataframe I start with, given by OP
df = df.groupby('Symbol').agg(np.mean)
for pair in lst:
    df[pair[0]+'-'+pair[1]] = df[pair[0]] - df[pair[1]]

print(df)
             C1      C2      C3     C4   C1-C2   C1-C3  C3-C4
Symbol                                                       
A       12.1750  11.500  15.675  9.400  0.6750 -3.5000  6.275
B        8.2075  10.975  16.500  7.925 -2.7675 -8.2925  8.575
from scipy.stats import ttest_ind

lst = [['C1','C2'], ['C1','C3'], ['C3','C4']]

df_group = df.groupby('Symbol').sum()

for l in lst:
    df_group[l[0]+'-'+l[1]+' pval'] = ttest_ind(df_group[l[0]], df_group[l[1]])[1]

# Drop columns not needed anymore    
df = df_group.drop(['C1', 'C2', 'C3', 'C4'],axis=1)

# Sort columns to get expected output
df = df.reindex(sorted(df.columns), axis=1).reset_index()

print(df)
  Symbol   C1-C2  C1-C2 pval   C1-C3  C1-C3 pval  C3-C4  C3-C4 pval
0      A  0.6750    0.653228 -3.5000    0.100586  6.275    0.012706
1      B -2.7675    0.653228 -8.2925    0.100586  8.575    0.012706

Спасибо за ответ Эрфан. Я думаю, что это приближает меня к возможному решению, однако я ожидаю, что значения p будут разными для «A» и «B» в каждом сравнении, поэтому похоже, что тест проводился для всего, а не для каждой группы?

CPfeif13 17.03.2019 15:32
Ответ принят как подходящий

Эврика!

Исходя из того, что я написал в вопросе:

import pandas as pd
import numpy as np
from scipy.stats import ttest_ind
df = pd.DataFrame([['A', 12.1, 11.4, 15.1, 9.9], ['B', 8.3, 10.3, 16.6, 7.8], ['B', 7.8, 11.1, 16.3, 8.4], 
                   ['B', 8.6, 10.9, 16.4, 8.1], ['A', 12.25, 11.6, 16.25, 8.9], ['B', 8.13, 11.6, 16.7, 7.4]
                  ], columns = ['Symbol', 'C1','C2', 'C3', 'C4'])
lst = [['C1','C2'], ['C1','C3'], ['C3','C4']]

Сначала я нахожу разницу между парами в списке:

df2 = df.groupby('Symbol').agg(np.mean)
for pair in lst:
    df2[pair[0]+'-'+pair[1]] = df2[pair[0]] - df2[pair[1]]

Затем я составляю список «Символы» и перебираю его, чтобы создать новые кадры данных, содержащие только один и тот же символ для t-теста, который я затем добавляю к кадру данных, который имеет различия:

lst2 = list(set(df.Symbol))
for item in lst2:
    df3 = df[df.Symbol == item]
    for pair in lst:
        df2.loc[item, pair[0]+'-'+pair[1]+' pval'] = ttest_ind(df3[pair[0]], df3[pair[1]])[1]

Это приводит к кадру данных (df2):

    C1  C2  C3  C4  C1-C2   C1-C3   C3-C4   C1-C2 pval  C1-C3 pval  C3-C4 pval
Symbol                                      
A   12.1750 11.500  15.675  9.400   0.6750  -3.5000 6.275   0.032625    2.636815e-02    1.442745e-02
B   8.2075  10.975  16.500  7.925   -2.7675 -8.2925 8.575   0.000124    9.784611e-09    2.636731e-08

Затем я могу отбросить столбцы со средними значениями (C1, C2...), чтобы получить желаемый результат.

Другие вопросы по теме