【问题标题】:How do I do a F-test in python如何在 python 中进行 F 测试
【发布时间】:2014-02-24 23:28:47
【问题描述】:

如何进行 F 检验以检查 Python 中两个向量的方差是否相等?

例如,如果我有

a = [1,2,1,2,1,2,1,2,1,2]
b = [1,3,-1,2,1,5,-1,6,-1,2]

有没有类似的东西

scipy.stats.ttest_ind(a, b)

我找到了

sp.stats.f(a, b)

但这似乎与 F 检验不同

【问题讨论】:

  • 如果你只想测试等方差,scipy 有 BartlettLevene 测试。

标签: python statistics


【解决方案1】:

等方差的检验统计量 F 检验很简单:

F = Var(X) / Var(Y)

F 分发为df1 = len(X) - 1, df2 = len(Y) - 1

您在问题中提到的scipy.stats.f 具有CDF 方法。这意味着您可以为给定的统计数据生成一个 p 值并测试该 p 值是否大于您选择的 alpha 水平。

因此:

alpha = 0.05 #Or whatever you want your alpha to be.
p_value = scipy.stats.f.cdf(F, df1, df2)
if p_value > alpha:
    # Reject the null hypothesis that Var(X) == Var(Y)

请注意,F 检验对 X 和 Y 的非正态性极为敏感,因此您最好进行更稳健的检验,例如 Levene's testBartlett's test,除非您有理由确定 X和 Y 正态分布。这些测试可以在scipy api 中找到:

【讨论】:

  • 这个答案在数学上是正确的,但在概念上是错误的。 p_value 是1 - CDF。这是您的 F_critical 上方概率分布下的区域。我会这样写:p_value = scipy.stats.f.sf(F, df1, df2) 我认为生存函数的计算方式略有不同,所以你要仔细检查以防你处理非常小的 p_values(由于多重比较)然后你拒绝零假设如果p_value < alpha
  • 如果 p 值小于 0.05 或大于 0.95,方差是否没有显着差异?如果 F = 0.25,即 Y 的方差是 X 的方差的 4 倍(假设 df1 = df2 = 10),则基于 1 - CDF 的 p = 0.98。因此,我会选择小于 0.05 或大于 0.95 来测试显着不同的方差。
  • 我个人建议不要对非正态数据使用 Bartlett 检验,因为在“适度”偏离正态的情况下,统计数据不可靠。 Levene's 会更好。
【解决方案2】:

对于任何来这里搜索方差分析 F 检验或比较模型以进行特征选择的人

【讨论】:

    【解决方案3】:

    要做一个你可以使用的单一方法 anova

    import scipy.stats as stats
    
    stats.f_oneway(a,b)
    

    Anova 检查组间方差是否大于组内方差的一种方法,并使用 F 分布计算观察到此方差比的概率。一个很好的教程可以在这里找到:

    https://www.khanacademy.org/math/probability/statistics-inferential/anova/v/anova-1-calculating-sst-total-sum-of-squares

    【讨论】:

    • 假设 OP询问了比较两个样本的方差,测试统计量是样本方差的比率。如果您对两组进行 ANOVA,综合 F 检验统计值将是组间方差与组内方差的比率,这不是一回事。试试吧! :-)
    【解决方案4】:

    如果你需要一个双尾测试,你可以按照下面的方法进行,我选择了 alpha =0.05:

    a = [1,2,1,2,1,2,1,2,1,2]
    b = [1,3,-1,2,1,5,-1,6,-1,2]
    print('Variance a={0:.3f}, Variance b={1:.3f}'.format(np.var(a, ddof=1), np.var(b, ddof=1)))
    fstatistics = np.var(a, ddof=1)/np.var(b, ddof=1) # because we estimate mean from data
    fdistribution = stats.f(len(a)-1,len(b)-1) # build an F-distribution object
    p_value = 2*min(fdistribution.cdf(f_critical), 1-fdistribution.cdf(f_critical))
    f_critical1 = fdistribution.ppf(0.025)
    f_critical2 = fdistribution.ppf(0.975)
    print(fstatistics,f_critical1, f_critical2 )
    if (p_value<0.05):
        print('Reject H0', p_value)
    else:
        print('Cant Reject H0', p_value)
    

    如果您想进行类似方差分析的测试,只有较大的值会导致拒绝,您可以进行右尾测试,您需要注意方差的顺序(fstatistics = var1/var2 或 var2/var1 ):

    a = [1,2,1,2,1,2,1,2,1,2]
    b = [1,3,-1,2,1,5,-1,6,-1,2]
    print('Variance a={0:.3f}, Variance b={1:.3f}'.format(np.var(a, ddof=1), np.var(b, ddof=1)))
    fstatistics = max(np.var(a, ddof=1), np.var(b, ddof=1))/min(np.var(a, ddof=1), np.var(b, ddof=1)) # because we estimate mean from data
    fdistribution = stats.f(len(a)-1,len(b)-1) # build an F-distribution object 
    p_value = 1-fdistribution.cdf(fstatistics)
    f_critical = fd.ppf(0.95)
    print(fstatistics, f_critical)
    if (p_value<0.05):
        print('Reject H0', p_value)
    else:
        print('Cant Reject H0', p_value)
    

    左尾可以做如下:

    a = [1,2,1,2,1,2,1,2,1,2]
    b = [1,3,-1,2,1,5,-1,6,-1,2]
    print('Variance a={0:.3f}, Variance b={1:.3f}'.format(np.var(a, ddof=1), np.var(b, ddof=1)))
    fstatistics = min(np.var(a, ddof=1), np.var(b, ddof=1))/max(np.var(a, ddof=1), np.var(b, ddof=1)) # because we estimate mean from data
    fdistribution = stats.f(len(a)-1,len(b)-1) # build an F-distribution object
    p_value = fdistribution.cdf(fstatistics)
    f_critical = fd.ppf(0.05)
    print(fstatistics, f_critical)
    if (p_value<0.05):
        print('Reject H0', p_value)
    else:
        print('Cant Reject H0', p_value)
    

    【讨论】:

      【解决方案5】:

      这是一个使用 Python 和 SciPy 计算单面或双面 F 检验的简单函数。已根据 R 中 var.test() 函数的输出检查了结果。请记住其他答案中提到的有关 F 检验对非正态性的敏感性的警告。

      import scipy.stats as st
      
      def f_test(x, y, alt="two_sided"):
          """
          Calculates the F-test.
          :param x: The first group of data
          :param y: The second group of data
          :param alt: The alternative hypothesis, one of "two_sided" (default), "greater" or "less"
          :return: a tuple with the F statistic value and the p-value.
          """
          df1 = len(x) - 1
          df2 = len(y) - 1
          f = x.var() / y.var()
          if alt == "greater":
              p = 1.0 - st.f.cdf(f, df1, df2)
          elif alt == "less":
              p = st.f.cdf(f, df1, df2)
          else:
              # two-sided by default
              # Crawley, the R book, p.355
              p = 2.0*(1.0 - st.f.cdf(f, df1, df2))
          return f, p
      

      【讨论】:

      • 在标准统计实践中,ddof=1 提供了假设无限总体方差的无偏估计量。 ddof=0 提供了正态分布变量方差的最大似然估计。
      • @JustDoIt 谢谢,但我使用这个 Python 函数的目标是完全在 R 中重现 var.test() 函数的输出。因此我不想弄乱@ 987654324@ 设置。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-06
      • 1970-01-01
      • 2015-04-06
      • 1970-01-01
      • 2017-06-13
      • 2016-03-22
      • 1970-01-01
      相关资源
      最近更新 更多