You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用向量化操作加速Pandas每行的2x2 Fisher精确检验?

问题背景

给定如下Pandas DataFrame:

import pandas as pd
import numpy as np

arr = {
       "A" :[75.3,85.2,90.1,80.4,70.9],
       "B" :[80.6,90.2,85.7,70.8,95.1],
       "C" :[85.2,95.6,80.8,90.4,75.1],
       "D" :[90.3,85.5,80.0,70.5,95.2]
              }

df = pd.DataFrame(arr)

需要对每行构造2x2矩阵[[df["A"][i], df["B"][i]], [df["C"][i], df["D"][i]]],执行2x2 Fisher精确检验,并将检验得到的p值存入DataFrame的新列。

现有实现(循环方式)

目前通过循环调用scipy.stats.fisher_exact()实现功能,但大数据量下效率较低:

import scipy.stats as stats
pvalue = []

for i in df.index.values:
    a = df["A"][i]
    b = df["B"][i]
    c = df["C"][i]
    d = df["D"][i]
    
    data = [[a,b],[c,d]]
    
    odd_value, p_value = stats.fisher_exact(data)
    pvalue.append(p_value)
    
df["p_value"] = np.array(pvalue)
优化方案

1. 基于NumPy/Scipy的向量化实现

scipy.stats.fisher_exact()本身不支持直接向量化输入,但可以利用Fisher精确检验与超几何分布的关联,通过scipy.stats.hypergeom的向量化接口批量计算p值。

Fisher精确检验的核心逻辑对应超几何分布的累积概率计算,以下是向量化实现代码:

import scipy.stats as stats

# 提取所有行的a,b,c,d为numpy数组
a = df["A"].values
b = df["B"].values
c = df["C"].values
d = df["D"].values

# 计算超几何分布的参数
n = a + b + c + d  # 总样本数
k = a + c          # 第一行总和
M = a + b          # 第一列总和

# 计算双侧p值(与fisher_exact默认逻辑一致)
cdf_val = stats.hypergeom.cdf(a, n, M, k)
sf_val = stats.hypergeom.sf(a - 1, n, M, k)
p_values = np.minimum(cdf_val, sf_val) * 2

# 修正极端情况(避免p值超过1)
p_values = np.where(p_values > 1, 1, p_values)

df["p_value_vectorized"] = p_values

该实现完全基于向量化操作,避免了Python循环,在大数据量下效率会大幅提升,且结果与原循环方式一致。

2. 更高效的替代函数

如果需要进一步提升性能,可以选择以下方案:

  • Numba加速循环:用numba.jit将Python循环编译为机器码执行,大幅降低运行开销:
from numba import jit
import scipy.stats as stats

@jit(nopython=True)
def fisher_exact_numba(a, b, c, d):
    p_values = np.empty(len(a))
    for i in range(len(a)):
        table = [[a[i], b[i]], [c[i], d[i]]]
        _, p = stats.fisher_exact(table)
        p_values[i] = p
    return p_values

df["p_value_numba"] = fisher_exact_numba(a, b, c, d)
  • Cython手动编译:对于极致性能需求,可使用Cython编写底层循环逻辑,进一步消除Python解释器开销,但实现成本较高。

注意:Fisher精确检验涉及阶乘/对数阶乘计算,scipy内部已做数值稳定处理,上述方案均继承了这一特性。


内容的提问来源于stack exchange,提问作者infinity26484

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 15:47:46