是否可以对两个数据集中出现的字符串进行显着性测试

机器算法验证 统计学意义 Python
2022-03-23 09:57:54

我有两组从不同来源编译的数据。两组数据都包含具有出现频率的单词。我想检查两个数据集中是否存在某个单词,如果存在,是否可以进行某种统计学上的显着性检验以证明该单词是显着的。

例如:

word = 'apple'
dict1 = {'oranges': 45, 'apple': 34, ..., 'x': y}
dict2 = {'apple': 165, 'orange': 12, ..., 'x': y}

如果两个数据集(dict1 和 dict2)中都出现了单词“apple”,则计算单词 apple 的显着性检验。

编辑:

  1. 首先,我想检查两个数据集中是否存在这两个词。

  2. 例如,如果 dict 有 1000 个单词,我按照频率排列单词,我会得到某种图表。如果顶部单词的频率为 13,000,而“apple”的频率为 34,我想测试一下差距(13,000 - 34)是否太大,并且“apple”这个词与最重要的词被认为是重要的。但是,如果 80% 的词都在 20-50 的频率范围内,那么说“apple”不重要就不是一个好主意。

  3. 我有 2 个数据集,其中可能出现“苹果”一词。所以,我需要确保“苹果”在任一或两个数据集中的频率值不会太低。

2个回答

注意:根据 OP 添加的新信息,现在不推荐使用此答案。该答案与上下文相关,因此未删除。

如果单词同时出现在两个字典中,您可以对比例相等进行 z 检验。

这个过程有两个步骤——Python和统计的组合:

  1. 有效地创建常用词的字典,计算它们在每个样本中的相对计数。
  2. 计算两个样本的比例测试,同样有效地用于整个通用词典。

高效创建常用词典

计算比例的一种有效方法(注意所有代码都是 Python 3.3)是使用字典推导:

import math as math
import scipy.stats as sps
from collections import defaultdict

dictA = {'word1': 1, 'word2': 4, 'word7': 99, 'word13': 17}
dictB = {'word71': 1, 'word3': 4, 'word2': 99, 'word7': 17, 'word9': 45}

# compute the sums of the frequencies of occurrence of all the words
#     NOTE this is expensive, but is done only once
sumValuesA = sum(dictA.values())
sumValuesB = sum(dictB.values())

dictAB = {key: (value, dictB.get(key)) for key, 
          value in dictA.items() if key in dictB.keys()}
print(dictAB)

现在您有了一个字典,其中包含任一字典中单词的计数。您可以使用 形成您选择的比例测试dictAB

比较样本之间的比例

可以根据给定次数的试验中的成功比例来检验两个给定样本的成功概率是否在统计上相等。

为了清楚起见,在下文中,样本是包含单词的两个文档,试验是任一文档中的单词总数,成功是任一文档中特定单词的总数。

其中是总体 1 的成功概率,是样本 2 的成功概率。H0:p1=p2p1p2

检验统计量为

Z=p^1p^2p^(1p^)(1N1+1N2)

其中是第 j 个群体中的成功次数群体中的试验次数人口,和p^j=XjNj,j=1,2XjjNjjp^=X1+X2N1+N2

在原假设下,该统计量是标准正态分布的。这是执行此操作的 Python 代码:

#================================================
# compute the two sample difference of proportions
#================================================
def fnDiffProp(x1, x2, n1, n2):
    '''
    inputs:
    x1: the number of successes in the first sample
    x2: the number of successes in the second sample
    n1: the total number of 'trials' in the first sample
    n2: the total number of 'trials' in the second sample
    output:
    the test statistic, and the p-value as a tuple
    '''
    hatP = (x1 + x2)/(n1 + n2)
    hatQ = 1 - hatP
    hatP1 = x1/n1
    hatP2 = x1/n2
    Z = (hatP1 - hatP2)/(math.sqrt(hatP*hatQ*(1/n1 + 1/n2)))
    pVal = 2*(1 - sps.norm.cdf(Z))
    return((Z, pVal))

# apply the function above to each of the common words across the
#     two samples
dictPropTest = {key: fnDiffProp(value[0], value[1],
                                 sumValuesA, sumValuesB) for key, value in dictAB.items() }

例如,“word7”的比例差异在文档中非常显着,而“word2”则不然。

您想知道不同组中相同单词的计数(间隙)之间的差异何时出乎意料地大。听起来你假设不同群体之间的差距一般来说应该很小。您也只有 2 组计数 - 您只提供 2 个数据集 - 这会使测试显着性变得困难。

您可以尝试贝叶斯方法,前提是您愿意做出一些假设。 贝叶斯定理将您拥有的数据与您的数据来自的分布相关联。具体来说,当应用于您的问题的多个假设时,该定理看起来像:

P(H1|Gap)=P(Gap|H1)P(H1)P(Gap|H1)P(H1)+P(Gap|H2)P(H2)

对于第一个假设和

P(H2|Gap)=P(Gap|H2)P(H2)P(Gap|H1)P(H1)+P(Gap|H2)P(H2)

第二个。这里的问题是的定义:它们是什么以及如何指定它们?一旦你知道它们是什么,那么条件分布呢? H1H2

我尝试在 Python 中执行此操作(代码/结果如下),但首先,我是如何回答这些问题的。

我假设您不知道单词的 2 个计数之间的 Gap 应该大还是小,所以我假设对于每个单词,它可以以任何一种方式出现,有 50/50 的机会并设置P(H1)=0.5P(H2)=0.5

接下来,条件句呢?好吧,你想知道给定一些预期差距大小的差距的概率。由于间隙将是整数,因此将间隙的分布建模为泊松分布是有意义的,每个假设都有自己的参数。也就是说,每个都有一个不同的HλHPois(λ,Gap)λ

这些假设是在没有真实数据的情况下做出的,这就是这种方法的缺点。话虽这么说,下面是一个实现的样子:

import math

def pois(l, k):
  return math.exp(-l) * (l**k)/math.factorial(k)

def bayes_test(h1, h2, gap):
  lp1 = pois(h1, gap) * 0.5
  lp2 = pois(h2, gap) * 0.5
  pb = lp1 + lp2

  print ''.join(["P( H1 | gap ): ", str(lp1/pb), "\nP( H2 | gap ): ", str(lp2/pb)])
  return [lp1/pb, lp2/pb]

以下是可能的输出:

>>> bayes_test(7, 30, 10)
P( H1 | gap ): 0.999785530317
P( H2 | gap ): 0.000214469683207
[0.9997855303167933, 0.00021446968320674848]

使用我定义的泊松分布函数,我们设置,这意味着我们的假设是的预期 Gap 大小是 7或的 30 ,我们用一些观察到的 Gap 大小进行测试 10 . 然后我们看到,我们的数据更有可能用 7 的预期 Gap 大小来解释,而不是 30。λ1=7λ2=30H1H2

因此,要点是,如果您可以修改您的问题以询问几个假设,您可以使用贝叶斯方法来询问哪个假设更有可能。