【发布时间】:2017-09-03 06:55:43
【问题描述】:
我不确定实现我想要的最佳/最合理的统计方法是什么,但我基本上是在尝试获取 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)]
然后我可以轻松地使用这些边界和标签来制作两个直方图,按原始向量的长度加权。最简单的方法就是使用几个 bin 并将它们绘制为同一轴上的直方图,就像在这个问题中一样:
但是,我真的想要更像 QQ 图的东西,并且我想使用很多 bin,这样我就可以看到与 1 对 1 线的微小偏差。仅绘制两个直方图的问题在于它们看起来像这样:
这两个地块正好在彼此之上,我什么都看不到。
所以我想弄清楚的是如何比较这两个直方图同时保持 bin 标签。我可以轻松地将两者相互绘制为散点图,但最终会被 bin 频率索引:
我真正想要的只是比较两个直方图,或者制作差异的 QQ 图,但我无法提出一个好的统计方法来做到这一点。我找不到任何方法可以让我使用两个数据集而不是一个数据集和一个内置分布来制作 QQ 图,而且我找不到任何方法来绘制两个长度不等的分布。
作为参考,这里是创建该图的两个直方图,您可以看到它们非常相似:
我知道一定有一个好的方法可以做到这一点,因为它看起来很明显,但我对这种东西很陌生,对 scipy、pandas 和 statsmodels 也比较陌生。
我故意没有在这里提供示例分布,因为我不确定如何制作一组非正态分布的最小数组并捕获我想要做的事情;再加上一点是能够为任何两个重叠的不等长数组做到这一点。
我想知道的是,在 python 中以统计上合理的方式解决此问题的正确/最佳方法是什么?是否有某种方法可以从可用于 statsmodels 或 scipy QQ 图的置换数据创建分布?有没有办法像这样在视觉上比较两个直方图?有没有办法制作我不知道的概率图?
编辑:尝试累积和手动 QQ 图
感谢@user333700 的回答,我想出了如何为数据创建手动QQ 图,以及累积概率图。我使用具有重叠最小值/最大值但具有以下分布的数据创建了图:
QQ图:
q = np.linspace(0, 100, 101)
fig, ax = plt.subplots()
ax.scatter(np.percentile(ytest, q), np.percentile(xtest, q))
所以这对简单数据非常有效,累积图是相似的:
# 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()
回到我的实际倾斜数据(除了长度之外,这两个分布在各方面都非常相似)并添加了一对一的线,我得到了这两个数据:
所以两者都起作用,这很好,累积概率图很清楚地表明数据没有大的差异,但QQ图显示尾部有很小的差异。
【问题讨论】:
-
pp-plot 的小变化:直方图具有相等长度的 bin(长度为原始值),因此 pp-plot 的间距仍然不等。我们用于 pp-plot 的是等重箱。例如,使用由 x 的每个第 k 个观测值定义的 bin 边界,用这些 bin 对两个系列进行 bin,然后绘图。在这种情况下,x 累积直方图频率将在 [0,1] 中等间距。
-
@user333700:你能澄清一下吗?在这种情况下,恐怕我不理解您所说的等重箱的意思。您能否提供一个伪代码示例来说明我将如何做到这一点?
-
在您的概率图中,您的点的 x 坐标对应于每个 bin 的累积概率。因为 bin 具有不同的频率或计数,所以点的 x 坐标会移向大部分概率所在的末端,例如你只有两个低于中位数的箱子。相反,如果您选择 bin 边界,以便这些 bin 对 x 变量具有相同的频率,则绘图点将在 x 轴上等间距。
boundaries = sorted(x)[::k]之类的东西和端点的调整。使用“相等的权重”,我的意思是每个 bin 中 x 的频率相等。 -
概率图现在在 x 上等间距,即边界看起来正确。但是,我对 pandas 不够熟悉,无法仅通过阅读来理解代码。鉴于您的示例中两个分布的差异,概率图点应该远离 45 度线弯曲或弯曲。如果它是您的实际数据具有基本相等的分布,那么它确认分布在分布的任何部分都没有差异。
-
(顺便说一句:qq-plot 使异常值和尾部差异更加明显,pp-plot 使中心差异更加明显,因为端点固定在 0 和 1。)
标签: python matplotlib scipy statistics statsmodels