Python Q-Q和两个不等长

时间:2017-04-07 19:27:35

标签: python matplotlib scipy statistics statsmodels

我不确定实现我想要的最佳/最具统计学效果的方法是什么,但我基本上试图分配p值并将其与通过置换产生的更大的p值分布进行比较我的原始数据。我正在处理小的p值,所以我实际上是在比较p值的log10。

我一直试图找出一种很好的通用方法来比较具有相似值但长度不等的两个数组。我真正想要的是像scipy.qqplot(dataset1, dataset2)这样的东西,但这并不存在,QQ图只会将你的分布与已建立的分布进行比较(这个问题也被要求R也是:https://stats.stackexchange.com/questions/12392/how-to-compare-two-datasets-with-q-q-plot-using-ggplot2)。

基本上这相当于比较两个直方图。我可以使用np.linspace为每个分发强制使用完全相同的bin:

bins = 100
mx = max(np.max(vector1), np.max(vector2))
mn = min(np.min(vector2), np.max(vector2))
boundaries = np.linspace(mn, mx, bins, endpoint=True)
labels = [(boundaries[i]+boundaries[i+1])/2 for i in range(len(boundaries)-1)]

然后,我可以轻松地使用这些边界和标签来制作两个直方图,按原始矢量的长度加权。最简单的方法就是使用几个箱子并将它们绘制在同一轴上的直方图上,就像这个问题一样:

然而,我真的想要更像Q-Q情节的东西,我想要使用很多分档,这样我就可以看到与1对1线的偏差很小。只绘制两个直方图的问题是它们看起来像这样:

histogram_example

这两个地块恰好相互叠加,我看不到任何东西。

所以我想弄清楚,如何比较这两个直方图,同时保持bin标签。我可以很容易地将两者相互映射为散点图,但最终会被bin频率编入索引:

definitely wrong

我真正想要的是比较两个直方图,或者制作差异的Q-Q图,但我无法想出一个好的统计上合理的方法。我找不到允许我用两个数据集而不是一个数据集和一个内置分布制作QQ图的方法,我找不到任何方法来绘制两个不等长度的分布。

作为参考,以下是创建该图的两个直方图,您可以看到它们非常相似:

histograms

我知道必须有一个很好的方法来做到这一点,因为它看起来很明显,但我对这种事情不熟悉,对scipy,pandas和statsmodel来说也相对较新。

我故意没有在这里提供一个示例分发,因为我不确定如何制作一组非正态分布的最小数组并捕获我想要做的事情;加上关键是能够为任何两个重叠的不等长数组做到这一点。

我想知道的是,以统计上合理的方式在python中解决此问题的正确/最佳方法是什么?是否有某种方法可以从置换数据创建分布,可用于statsmodels或scipy Q-Q图?有没有办法比较直观地比较两个直方图?有没有办法制作我不了解的概率图?

编辑:尝试累积和手动Q-Q图

感谢@ user333700的回答,我想出了如何为数据创建手动QQ图,以及累积概率图。我使用具有重叠最小值/最大值但以下分布的数据创建了图:

manufactured distributions

QQ情节:

q = np.linspace(0, 100, 101)
fig, ax = plt.subplots()
ax.scatter(np.percentile(ytest, q), np.percentile(xtest, q))

qqplot

因此,对于简单数据非常有效,累积图类似:

# Pick bins
x = ytest
y = xtest
boundaries = sorted(x)[::round(len(x)/bins)+1]
labels = [(boundaries[i]+boundaries[i+1])/2 for i in range(len(boundaries)-1)]

# Bin two series into equal bins
xb = pd.cut(x, bins=boundaries, labels=labels)
yb = pd.cut(y, bins=boundaries, labels=labels)

# Get value counts for each bin and sort by bin
xhist = xb.value_counts().sort_index(ascending=True)/len(xb)
yhist = yb.value_counts().sort_index(ascending=True)/len(yb)

# Make cumulative
for ser in [xhist, yhist]:
    ttl = 0
    for idx, val in ser.iteritems():
        ttl += val
        ser.loc[idx] = ttl

# Plot it
fig, ax = plt.subplots(figsize=(6,6))
ax.scatter(xhist, yhist)
plt.show()

cumulative plot

回到我的实际偏斜数据(除了长度之外,两个分布在各方面都非常相似)并添加1对1的行,我得到了这两个:

plots with real data

因此两者都很好,而且累积概率图非常清楚地表明数据没有大的差异,但Q-Q图显示尾部存在小的差异。

1 个答案:

答案 0 :(得分:2)

在统计检验方面,scipy对连续变量进行了两个样本Kolmogorov-Smirnov检验。分箱直方图数据可以与chisquare测试一起使用。 scipy.stats还有一个k样本的Anderson-Darling测试。

用于绘图:

两个直方图的概率图的等价物将是绘制两个样本的累积频率,即每个轴上对应于区间边界的累积概率。

statsmodels有一个qq-plot用于两个样本比较,但它目前假设样本大小相同。如果样本大小不同,则需要针对相同的概率计算分位数。 https://github.com/statsmodels/statsmodels/issues/2896 https://github.com/statsmodels/statsmodels/pull/3169 (我不记得这是什么状况。)