Вычислить pvalue из pandas DataFrame

У меня есть статистика DataFrame с Multindex и 8 образцами (здесь показаны только два) и 8 генами для каждого образца.

 In[13]:stats
    Out[13]: 
                       ARG/16S                                            \
                         count          mean           std           min   
    sample      gene                                                       
    Arnhem      IC        11.0  2.319050e-03  7.396130e-04  1.503150e-03   
                Int1      11.0  7.243040e+00  6.848327e+00  1.364879e+00   
                Sul1      11.0  3.968956e-03  9.186019e-04  2.499074e-03   
                TetB       2.0  1.154748e-01  1.627663e-01  3.816936e-04   
                TetM       4.0  1.083125e-04  5.185259e-05  5.189226e-05   
                blaOXA     4.0  4.210963e-06  3.783235e-07  3.843571e-06   
                ermB       4.0  4.111081e-05  7.894879e-06  3.288865e-05   
                ermF       4.0  2.335210e-05  4.519758e-06  1.832037e-05   
    Basel       Aph3a      4.0  7.815592e-06  1.757242e-06  5.539389e-06   
                IC        11.0  5.095161e-03  5.639278e-03  1.302205e-03   
                Int1      12.0  1.333068e+01  1.872207e+01  4.988048e-02   
                Sul1      11.0  1.618617e-02  1.988817e-02  2.970397e-03   

Я пытаюсь вычислить p-значение (t-критерий Стьюдента) для каждой из этих выборок, сравнивая каждый из генов между ними.

Я использовал scipy.stats.ttest_ind_from_stats, но мне удалось получить p-значения для разных образцов для одного гена и только для образцов, соседних друг с другом.

Experiments = list(values1_16S['sample'].unique())
for exp in Experiments:
    if Experiments.index(exp)<len(Experiments)-1:
        second = Experiments[Experiments.index(exp)+1]
    else:
        second = Experiments[0]
    tstat, pvalue = scipy.stats.ttest_ind_from_stats(stats.loc[(exp,'Sul1')]['ARG/16S','mean'],
                                    stats.loc[(exp,'Sul1')]['ARG/16S','std'],
                                    stats.loc[(exp,'Sul1')]['ARG/16S','count'],
                                    stats.loc[(second,'Sul1')]['ARG/16S','mean'],
                                    stats.loc[(second,'Sul1')]['ARG/16S','std'],
                                    stats.loc[(second,'Sul1')]['ARG/16S','count'])
    d.append({'loc1':exp, 'loc2':second, 'pvalue':pvalue})


stats_Sul1 = pd.DataFrame(d)
stats_Sul1

Как я могу получить значения p между ВСЕМИ образцами? И есть ли способ сделать это для всех генов сразу, не выполняя код по одному для каждого гена?

у вас одинаковые 8 генов для каждого образца? Я вижу Aph3a для второго образца, а не для первого.

Ben.T 02.05.2018 20:51

Да, у меня одинаковые гены для каждого образца. В первом примере Aph3 равен 0, поэтому здесь его нет.

Gabriela Catalina 03.05.2018 10:42

Вы можете проверить мой РЕДАКТИРОВАТЬ, я думаю, решение будет работать для любого количества образцов и генов, даже если они не совпадают

Ben.T 03.05.2018 16:03
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
3
10 628
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Предположим, у вас есть те же гены X для образцов Y. Я пробую свой метод с X = 3 и Y = 2, но я думаю, вы можете обобщить. Я начал с:

df1 = 
             count       mean        std       min
sample gene                                       
Arnhem IC       11   0.002319   0.000740  0.001503
       Int1     11   7.243040   6.848327  1.364879
       Sul1     11   0.003969   0.000919  0.002499
Basel  IC       11   0.005095   0.005639  0.001302
       Int1     12  13.330680  18.722070  0.049880
       Sul1     11   0.016186   0.019888  0.002970

Обратите внимание, что гены должны быть в одном порядке. Первый reset_index() с df_reindex = df1.reset_index(), я не уверен, что то, что я делаю, возможно с мультииндексом:

df_reindex =
   sample  gene  count       mean        std       min
0  Arnhem    IC     11   0.002319   0.000740  0.001503
1  Arnhem  Int1     11   7.243040   6.848327  1.364879
2  Arnhem  Sul1     11   0.003969   0.000919  0.002499
3   Basel    IC     11   0.005095   0.005639  0.001302
4   Basel  Int1     12  13.330680  18.722070  0.049880
5   Basel  Sul1     11   0.016186   0.019888  0.002970

Создаю свернутый DF и присоединяю его к df_reindex:

nb_genes = 3
df_rolled = pd.DataFrame(pd.np.roll(df_reindex,nb_genes,0), columns = df_reindex.columns)
df_joined = df_reindex.join(df_rolled, rsuffix='_')
# rsuffix='_' is to be able to perform the join

Теперь в той же строке у меня есть все данные, необходимые для вычисления pvalue и создания столбца с apply:

df_joined['pvalue'] = df_joined.apply(lambda x: stats.ttest_ind_from_stats(x['mean'],x['std'],x['count'], x['mean_'],x['std_'],x['count_'])[1],axis=1)

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

df_output = df_joined[['sample','sample_','gene','pvalue']].rename(columns = {'sample':'loc1', 'sample_':'loc2'})

Вы получаете данные:

df_output = 
     loc1    loc2  gene    pvalue
0  Arnhem   Basel    IC  0.121142
1  Arnhem   Basel  Int1  0.321072
2  Arnhem   Basel  Sul1  0.055298
3   Basel  Arnhem    IC  0.121142
4   Basel  Arnhem  Int1  0.321072
5   Basel  Arnhem  Sul1  0.055298

Что вы можете переиндексировать по мере необходимости.

Если вы хотите сделать это каждый сэмпл друг против друга, я думаю, что цикл for может это сделать.

Обновлено: Используя pivot_table, я думаю, что есть более простой способ.

С вашим входным stats в качестве мультииндексной таблицы только для ARG/16S (не знаю, как обрабатывать этот уровень), поэтому я начну с (это может быть ваш stats['ARG/16S']):

df=
               count       mean           std       min
sample gene                                            
Arnhem IC         11   0.002319  7.396130e-04  0.001503
       Int1       11   7.243040  6.848327e+00  1.364879
       Sul1       11   0.003969  9.186019e-04  0.002499
       TetB        2   0.115475  1.627663e-01  0.000382
       TetM        4   0.000108  5.185259e-05  0.000052
       blaOXA      4   0.000004  3.783235e-07  0.000004
       ermB        4   0.000041  7.894879e-06  0.000033
       ermF        4   0.000023  4.519758e-06  0.000018
Basel  Aph3a       4   0.000008  1.757242e-06  0.000006
       IC         11   0.005095  5.639278e-03  0.001302
       Int1       12  13.330680  1.872207e+01  0.049880
       Sul1       11   0.016186  1.988817e-02  0.002970

С помощью функции pivot_table вы можете переупорядочивать свои данные, например:

df_pivot = df.pivot_table(values = ['count','mean','std'], index = 'gene', 
                               columns = 'sample', fill_value = 0)

В этом df_pivot (я не печатаю его здесь для удобства чтения, но в конце с новым столбцом) вы можете создать столбец для каждой пары (sample1, sample2), используя itertools и apply:

import itertools
for sample1, sample2 in itertools.combinations(df.index.levels[0],2):
    # itertools.combinations create all combinations between your samples
    df_pivot[sample1+ '_' + sample2 ] = df_pivot.apply(lambda x: stats.ttest_ind_from_stats(x['mean'][sample1],x['std'][sample1],x['count'][sample1], 
                                                                                        x['mean'][sample2 ],x['std'][sample2 ],x['count'][sample2 ],)[1],axis=1).fillna(1)

Я думаю, что этот метод не зависит от количества образцов, генов, и если гены не все одинаковы, вы получите df_pivot, например:

        count            mean                      std            Arnhem_Basel
sample Arnhem Basel    Arnhem      Basel        Arnhem      Basel             
gene                                                                          
Aph3a       0     4  0.000000   0.000008  0.000000e+00   0.000002     1.000000
IC         11    11  0.002319   0.005095  7.396130e-04   0.005639     0.121142
Int1       11    12  7.243040  13.330680  6.848327e+00  18.722070     0.321072
Sul1       11    11  0.003969   0.016186  9.186019e-04   0.019888     0.055298
TetB        2     0  0.115475   0.000000  1.627663e-01   0.000000     1.000000
TetM        4     0  0.000108   0.000000  5.185259e-05   0.000000     1.000000
blaOXA      4     0  0.000004   0.000000  3.783235e-07   0.000000     1.000000
ermB        4     0  0.000041   0.000000  7.894879e-06   0.000000     1.000000
ermF        4     0  0.000023   0.000000  4.519758e-06   0.000000     1.000000

Сообщите мне, если это сработает

РЕДАКТИРОВАТЬ2:, чтобы ответить на комментарий, я думаю, вы можете это сделать:

Без изменений для df_pivot, а затем вы создаете мультииндексный DF df_multi для записи результатов в:

df_multi = pd.DataFrame(index = df.index.levels[1], 
                        columns = pd.MultiIndex.from_tuples([p for p in itertools.combinations(df.index.levels[0],2)])).fillna(0)

Затем вы используете цикл for для реализации данных в этом df_multi:

for sample1, sample2 in itertools.combinations(df.index.levels[0],2):
    # itertools.combinations create all combinations between your samples
    df_multi.loc[:,(sample1,sample2)] = df_pivot.apply(lambda x: stats.ttest_ind_from_stats(x['mean'][sample1],x['std'][sample1],x['count'][sample1], 
                                                                                        x['mean'][sample2 ],x['std'][sample2 ],x['count'][sample2 ],)[1],axis=1).fillna(1)

Наконец, вы можете использовать transpose и unstack на уровне 1, чтобы получить то, что вы просите (или закрыть, если я неправильно понял)

df_output = df_multi.transpose().unstack(level=[1]).fillna(1)

Вы увидите, что у вас нет последнего образца в индексах и первого образца в столбцах (потому что они не существуют, как я все построил), если они вам нужны, вам нужно заменить itertools.combinations на itertools.combinations_with_replacement как при создании df_multi, так и в шлейфе for (не пробовал но должно работать)

Спасибо за редактирование! Первое решение у меня не сработало. Пытаюсь отредактировать сейчас, но сначала мне нужно избавиться от этой первой строки MultiIndex («ARG / 16S»). Если я удаляю using, drop () он также удаляет все, что ниже. Я дам вам знать, если я заставлю его работать

Gabriela Catalina 03.05.2018 16:44

если делать df = stats['ARG/16S'] надо делать?

Ben.T 03.05.2018 16:48

Это сработало! Огромное спасибо! Знаете ли вы, есть ли также способ иметь образцы, которые сравниваются как индексы столбцов и строк и мультииндекс столбцов с генами? (Просто чтобы было легче найти pvalue)

Gabriela Catalina 03.05.2018 17:02

@GabrielaCatalina да, есть способ, я думал о том, как лучше всего создать выходные данные. Я попробую в своем EDIT2

Ben.T 03.05.2018 18:27

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