【问题标题】:How to implement R's p.adjust in Python如何在 Python 中实现 R 的 p.adjust
【发布时间】:2011-11-19 00:58:09
【问题描述】:

我有一个 p 值列表,我想为FDR 的多重比较计算调整 p 值。在 R 中,我可以使用:

pval <- read.csv("my_file.txt",header=F,sep="\t")
pval <- pval[,1]
FDR <- p.adjust(pval, method= "BH")
print(length(pval[FDR<0.1]))
write.table(cbind(pval, FDR),"pval_FDR.txt",row.names=F,sep="\t",quote=F )

如何在 Python 中实现此代码?这是我在 Google 的帮助下在 Python 中的成功尝试:

pvalue_list [2.26717873145e-10, 1.36209234286e-11 , 0.684342083821...] # my pvalues
pvalue_lst = [v.r['p.value'] for v in pvalue_list]
p_adjust = R.r['p.adjust'](R.FloatVector(pvalue_lst),method='BH')
for v in p_adjust:
    print v

以上代码抛出AttributeError: 'float' object has no attribute 'r' 错误。谁能帮忙指出我的问题?提前感谢您的帮助!

【问题讨论】:

    标签: python r statistics rpy2


    【解决方案1】:

    如果您希望确定您从 R 中得到了什么,您还可以表明您希望使用 R 包“stats”中的函数:

    from rpy2.robjects.packages import importr
    from rpy2.robjects.vectors import FloatVector
    
    stats = importr('stats')
    
    p_adjust = stats.p_adjust(FloatVector(pvalue_list), method = 'BH')
    

    【讨论】:

    • @Igautier 感谢您的帮助!当我运行你的代码时,Python 会抛出一个ImportError: No module named packages 错误。知道问题是什么吗?我正在运行 R 2.13.1。
    • 我会说您使用的是过时版本的 rpy2。如果不确定,请尝试 rpy2.__version__。当前是 2.2.2。
    • 是的,这对我来说适用于 R 2.2x。不幸的是,我坚持在远程服务器上使用 R 2.13.1。有什么建议吗?
    • hmmm... 我指的是 rpy2 版本,而不是 R 版本。向系统管理员询问 rpy2 升级或自己升级(考虑使用 Python 包“virtualenv”来创建自定义 Python)。
    • 很抱歉给您带来了困惑。我误读了你的cmets。我将本地 rpy2 更新为 2.2x,并且您的代码有效。非常感谢您的帮助!
    【解决方案2】:

    【讨论】:

    • @jseabold:嗨,关于multipletests 的快速问题?当与BH 一起使用时,此函数如何处理 p 值列表中的 NaN 值?似乎它假设所有 p 值都是有限的,对吗?
    【解决方案3】:

    这是我使用的内部函数:

    def correct_pvalues_for_multiple_testing(pvalues, correction_type = "Benjamini-Hochberg"):                
        """                                                                                                   
        consistent with R - print correct_pvalues_for_multiple_testing([0.0, 0.01, 0.029, 0.03, 0.031, 0.05, 0.069, 0.07, 0.071, 0.09, 0.1]) 
        """
        from numpy import array, empty                                                                        
        pvalues = array(pvalues) 
        n = float(pvalues.shape[0])                                                                           
        new_pvalues = empty(n)
        if correction_type == "Bonferroni":                                                                   
            new_pvalues = n * pvalues
        elif correction_type == "Bonferroni-Holm":                                                            
            values = [ (pvalue, i) for i, pvalue in enumerate(pvalues) ]                                      
            values.sort()
            for rank, vals in enumerate(values):                                                              
                pvalue, i = vals
                new_pvalues[i] = (n-rank) * pvalue                                                            
        elif correction_type == "Benjamini-Hochberg":                                                         
            values = [ (pvalue, i) for i, pvalue in enumerate(pvalues) ]                                      
            values.sort()
            values.reverse()                                                                                  
            new_values = []
            for i, vals in enumerate(values):                                                                 
                rank = n - i
                pvalue, index = vals                                                                          
                new_values.append((n/rank) * pvalue)                                                          
            for i in xrange(0, int(n)-1):  
                if new_values[i] < new_values[i+1]:                                                           
                    new_values[i+1] = new_values[i]                                                           
            for i, vals in enumerate(values):
                pvalue, index = vals
                new_pvalues[index] = new_values[i]                                                                                                                  
        return new_pvalues
    

    【讨论】:

    • 优秀的解决方案。我已将其移植到 python 3 并将其放在 github 的存储库中。如果您希望我将您的名字添加到版权行,请通过 PM 提供给我。
    【解决方案4】:

    使用 Python 的 numpy 库,完全不调用 R,这是 BH 方法的一个相当有效的实现:

    import numpy as np
    
    def p_adjust_bh(p):
        """Benjamini-Hochberg p-value correction for multiple hypothesis testing."""
        p = np.asfarray(p)
        by_descend = p.argsort()[::-1]
        by_orig = by_descend.argsort()
        steps = float(len(p)) / np.arange(len(p), 0, -1)
        q = np.minimum(1, np.minimum.accumulate(steps * p[by_descend]))
        return q[by_orig]
    

    (基于发布的 R 代码 BondedDust)

    【讨论】:

    • 应该是float(len(p)),否则就是整数除法
    【解决方案5】:

    (我知道这不是答案...只是想提供帮助。)R 的 p.adjust 中的 BH 代码只是:

    BH = {
            i <- lp:1L   # lp is the number of p-values
            o <- order(p, decreasing = TRUE) # "o" will reverse sort the p-values
            ro <- order(o)
            pmin(1, cummin(n/i * p[o]))[ro]  # n is also the number of p-values
          }
    

    【讨论】:

      【解决方案6】:

      老问题,但这里是用 python 翻译的 R FDR 代码(可能效率很低):

      def FDR(x):
          """
          Assumes a list or numpy array x which contains p-values for multiple tests
          Copied from p.adjust function from R  
          """
          o = [i[0] for i in sorted(enumerate(x), key=lambda v:v[1],reverse=True)]
          ro = [i[0] for i in sorted(enumerate(o), key=lambda v:v[1])]
          q = sum([1.0/i for i in xrange(1,len(x)+1)])
          l = [q*len(x)/i*x[j] for i,j in zip(reversed(xrange(1,len(x)+1)),o)]
          l = [l[k] if l[k] < 1.0 else 1.0 for k in ro]
          return l
      

      【讨论】:

        【解决方案7】:

        好吧,为了让您的代码正常工作,我想这样的事情会起作用:

        import rpy2.robjects as R
        
        pvalue_list = [2.26717873145e-10, 1.36209234286e-11 , 0.684342083821...] # my pvalues
        p_adjust = R['p.adjust'](R.FloatVector(pvalue_list),method='BH')
        for v in p_adjust:
            print v
        

        如果 p.adjust 足够简单,你可以用 Python 编写它,这样你就不需要调用 R。如果你想大量使用它,你可以制作一个简单的 Python 包装器:

        def adjust_pvalues(pvalues, method='BH'):
            return R['p.adjust'](R.FloatVector(pvalues), method=method)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-07-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-06-27
          • 1970-01-01
          • 2017-04-15
          • 2021-04-03
          相关资源
          最近更新 更多