【问题标题】:Fishers Exact Test from Pandas Dataframe来自 Pandas Dataframe 的 Fishers 精确测试
【发布时间】:2021-01-15 23:15:46
【问题描述】:

我正在尝试从数据框中的四列中找出使用 Fisher 精确检验创建 p 值的最佳方法。我已经提取了列联表的四个部分,'a' 是左上角,'b' 是右上角,'c' 是左下角,'d' 是右下角。我已经开始通过简单的 pandas 计算来包含额外的计算列,但如果有更简单的方法来使用 4 个初始列,则这些不是必需的。当包括一个额外的集合(x.type = high)时,我有超过 100 万行,所以想使用一种有效的方法。到目前为止,这是我的代码:

import pandas as pd
import glob
import math
path = r'directory_path'
all_files = glob.glob(path + "/*.csv")
li = []

for filename in all_files:
    df = pd.read_csv(filename, index_col=None, header=0)
    li.append(df)

frame = pd.concat(li, axis=0, ignore_index=True)
frame['a+b'] = frame['a'] + frame['b']
frame['c+d'] = frame['c'] + frame['d']
frame['a+c'] = frame['a'] + frame['c']
frame['b+d'] = frame['b'] + frame['d']

作为此数据的示例,“框架”当前显示:

    ID(n)   a   b   c   d   i   x.name  x.type  a+b     c+d     a+c     b+d
0   1258065     5   28  31  1690    1754    Albumin     low     33  1721    36  1718
1   1132105     4   19  32  1699    1754    Albumin     low     23  1731    36  1718
2   898621  4   30  32  1688    1754    Albumin     low     34  1720    36  1718
3   573158  4   30  32  1688    1754    Albumin     low     34  1720    36  1718
4   572975  4   23  32  1695    1754    Albumin     low     27  1727    36  1718
...     ...     ...     ...     ...     ...     ...     ...     ...     ...     ...     ...     ...
666646  12435   1   0   27  1726    1754    WHR     low     1   1753    28  1726
666647  15119   1   0   27  1726    1754    WHR     low     1   1753    28  1726
666648  17053   1   2   27  1724    1754    WHR     low     3   1751    28  1726
666649  24765   1   3   27  1723    1754    WHR     low     4   1750    28  1726
666650  8733    1   1   27  1725    1754    WHR     low     2   1752    28  1726

是将这些转换为 numpy 数组并通过迭代处理它的最佳方法,还是将其保存在 pandas 中?我假设我不能在数据框中使用数学函数(我试过math.comb(),它在数据框中不起作用)。我也尝试过使用 pyranges 作为它的 Fisher 方法,但它似乎不适用于我的环境(python 3.8)。

任何帮助将不胜感激!

【问题讨论】:

    标签: python python-3.x pandas statistics combinations


    【解决方案1】:

    根据来自 pyranges 的作者的answer here(我认为),假设您的数据类似于:

    import pandas as pd 
    import scipy.stats as stats
    import numpy as np
    
    np.random.seed(111)
    df = pd.DataFrame(np.random.randint(1,100,(1000000,4)))
    df.columns=['a','b','c','d']
    df['ID'] = range(1000000)
    
    df.head()
    
        a   b   c   d   ID
    0   85  85  85  87  0
    1   20  42  67  83  1
    2   41  72  58  8   2
    3   13  11  66  89  3
    4   29  15  35  22  4
    

    你把它转换成一个 numpy 数组,并像帖子中那样做:

    c = df[['a','b','c','d']].to_numpy(dtype='uint64')
    
    from fisher import pvalue_npy
    
    _, _, twosided = pvalue_npy(c[:, 0], c[:, 1], c[:, 2], c[:, 3])
    df['odds'] = (c[:, 0] * c[:, 3]) / (c[:, 1] * c[:, 2])
    
    df['pvalue'] = twosided
    

    或者你可以直接适配:

    _, _, twosided = pvalue_npy(df['a'].to_numpy(np.uint), df['b'].to_numpy(np.uint), 
                                df['c'].to_numpy(np.uint), df['d'].to_numpy(np.uint))
    
    df['odds'] = (df['a'] * df['d']) / (df['b'] * df['c'])
    df['pvalue'] = twosided
    

    【讨论】:

    • 谢谢。不幸的是,我在这方面遇到了错误。对于我得到的 Fisher 包方法:ValueError Traceback (most recent call last) <ipython-input-16-e90fc90e0b5d> in <module> 1 c = df[['a','b','c','d']].to_numpy(dtype='uint64') ----> 2 _, _, twosided = pvalue_npy(c[:, 0], c[:, 1], c[:, 2], c[:, 3]) 3 df['odds'] = (c[:, 0] * c[:, 3]) / (c[:, 1] * c[:, 2]) 4 5 df['pvalue'] = twosided src\cfisher.pyx in cfisher.pvalue_npy() ValueError: Buffer dtype mismatch, expected 'uint_t' but got 'unsigned long long'.
    • 对于另一种方法,我得到(缩短):ZeroDivisionError Traceback (most recent call last) <ipython-input-17-e78d1c46fba1> in <module> 2 df['c'].to_numpy(np.uint), df['d'].to_numpy(np.uint)) 3 ----> 4 df['odds'] = (df['a'] * df['d']) / (df['b'] * df['c']) 5 df['pvalue'] = twosided ZeroDivisionError: division by zero
    • 第一个..我认为你在做一些奇怪的事情..do type(c[0,0])你应该看到它是numpy.uint64
    • 我不使用 excel,所以我无法对此发表评论。当其中一个数字(a、b、c 或 d)变大时,可能难以估计两侧的 p 值。你做了很多测试,所以球场上的东西应该没问题。
    • 仅供参考,我刚刚将 c = df[['a','b','c','d']].to_numpy(dtype='uint64') 更改为 c = df[['a','b','c','d']].to_numpy(dtype='uint'),现在似乎可以正常工作了。
    猜你喜欢
    • 1970-01-01
    • 2021-07-10
    • 2016-08-25
    • 2018-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    相关资源
    最近更新 更多