概率分布函数 Python

Posted

技术标签:

【中文标题】概率分布函数 Python【英文标题】:Probability Distribution Function Python 【发布时间】:2016-07-09 02:18:39 【问题描述】:

我有一组原始数据,我必须确定这些数据的分布。绘制概率分布函数的最简单方法是什么?我已经尝试将其拟合为正态分布。

但我更想知道数据本身携带哪种分布?

我没有代码来显示我的进度,因为我在 python 中找不到任何可以让我测试数据集分布的函数。我不想对数据进行切片并强制它适应可能是正态分布或偏斜分布。

有什么方法可以确定数据集的分布吗?任何建议表示赞赏。

这是正确的方法吗? Example 这与我正在寻找的东西很接近,但它再次使数据符合正态分布。 Example

编辑:

输入有百万行,下面给出了简短的样本

Hashtag,Frequency
#Car,45
#photo,4
#movie,6
#life,1

频率范围从120,000 计数,我正在尝试确定关键字频率的分布。我尝试绘制一个简单的直方图,但我将输出作为单个条形图。

代码:

import pandas
import matplotlib.pyplot as plt


df = pandas.read_csv('Paris_random_hash.csv', sep=',')
plt.hist(df['Frequency'])
plt.show()

输出

【问题讨论】:

第一步:绘制直方图,然后查看 :) @cel 谢谢这是我一直在寻找的,我的下一个疑问是我是否像绘制 CDF 和 CCDF 时那样对数据进行排序? 直方图不像你想象的那样,你试着显示一个条形图。直方图需要列表中的每个数据点,而不是频率本身。你有 [3,2,0,4,...] 回合应该有 [1,1,1,2,2,4,4,4,4]。您无法自动确定概率分布:stats.stackexchange.com/questions/10517/… Here are all the scipy.stats distributions PDFs with example code. 【参考方案1】:

这是显示直方图的最小工作示例。它只能解决您的部分问题,但它可能是朝着您的目标迈出的一步。请注意,histogram 函数会为您提供 bin 两个角的值,您必须进行插值以获得中心值。

import numpy as np
import matplotlib.pyplot as pl

x = np.random.randn(10000)

nbins = 20

n, bins = np.histogram(x, nbins, density=1)
pdfx = np.zeros(n.size)
pdfy = np.zeros(n.size)
for k in range(n.size):
    pdfx[k] = 0.5*(bins[k]+bins[k+1])
    pdfy[k] = n[k]

pl.plot(pdfx, pdfy)

您可以使用以下示例拟合您的数据:

Fitting empirical distribution to theoretical ones with Scipy (Python)?

【讨论】:

Here are all the scipy.stats distributions PDFs with example code.【参考方案2】:

绝对是一个统计问题 - 听起来您正在尝试对分布是否与正态、对数正态、二项式等分布显着相似进行概率测试。最简单的方法是测试正态或对数正态,如下所述。

设置你的 Pvalue 截止值,通常如果你的 Pvalue

在 Python 中使用 SciPy,你只需要返回你的 P 值来测试,所以这个函数有 2 个返回值(为了清楚起见,我在这里忽略了可选(不需要)输入):

import scipy.stats

[W, Pvalue] = scipy.stats.morestats.shapiro(x)

执行 Shapiro-Wilk 正态性检验。 Shapiro-Wilk 检验检验数据来自正态分布的原假设。

如果你想看看它是否是对数正态分布的(前提是没有通过上面的P检验),你可以试试:

import numpy

[W, Pvalue] = scipy.stats.morestats.shapiro(numpy.log(x))

以同样的方式解释 - 我刚刚在已知的对数正态分布模拟上进行了测试,在 np.log(x) 测试中得到了 0.17 Pvalue,在标准 shapiro(x) 测试中得到了接近 0 的数字。这告诉我对数正态分布是更好的选择,正态分布会惨遭失败。

我把它简单化了,这就是我收集到的你正在寻找的东西。对于其他发行版,您可能需要按照 QQ 图https://en.wikipedia.org/wiki/Q%E2%80%93Q_plot 的方式做更多的工作,而不是简单地遵循我提出的一些测试。这意味着你有一个你试图拟合的分布图与你绘制的数据。如果您愿意,下面是一个可以让您走上这条道路的快速示例:

import numpy as np 
import pylab 
import scipy.stats as stats

mydata = whatever data you are looking to fit to a distribution  
stats.probplot(mydata, dist='norm', plot=pylab)
pylab.show()

您可以在上面替换任何来自 scipy 库 http://docs.scipy.org/doc/scipy/reference/tutorial/stats/continuous.html#continuous-distributions-in-scipy-stats 的 dist='norm' 然后找到它的 scipy 名称(必须根据文档添加形状参数,例如 stats.probplot(mydata, dist='loggamma', sparams=(1,1), plot=pylab) 或学生 T stats.probplot(mydata, dist='t', sparams=(1), plot=pylab)),然后查看绘图并查看您的数据与该分布的接近程度。如果数据点很接近,您就找到了您的分布。它也会在图表上为您提供 R^2 值;一般来说,越接近 1 越适合。

如果您想继续尝试使用数据框执行您正在执行的操作,请尝试更改为:plt.hist(df['Frequency'].values)

如果它回答了你的问题,请投票给这个答案 :) 需要一些赏金来获得对我自己的编程困境的答复。

【讨论】:

Matt 非常感谢您的精彩详细解释。我正在寻找在谷歌搜索时找不到的细节。这可能是一个统计问题或编程问题,但总而言之,对于刚刚进入数据科学领域并正在自己进行实验的人来说,这非常重要。非常感谢。再次感谢。 Here are all the scipy.stats distributions PDFs with example code.【参考方案3】:

您是否尝试过使用 seaborn 库?他们有一个很好的核密度估计函数。试试:

import seaborn as sns
sns.kdeplot(df['frequency'])

你找到安装说明here

【讨论】:

我曾与 seaborn 合作过,但尚未确定是否会检查,而且我的数据恰好是离散的,所以它是否适用? 我确实尝试实施您提供的解决方案,它对我来说看起来不错,但是当我尝试在 seaborn 中实施分布图时,kde 绘图很好,但切换到 hist 它会进入无限循环并且不会返回任何关于此的任何建议? @SitzBlogz 如果您对某些代码有疑问并且需要帮助调试它,请将其添加到您的问题中,或者最好再问一个问题。【参考方案4】:

数据本身携带的唯一分布是empirical probability。如果您的数据是一维 numpy 数组 data,您可以计算 empirical distribution function 在 x 的值,作为小于或等于 x 的值的累积相对频率:

d[d <= x].size / d.size

这是一个阶跃函数,因此它没有关联的概率密度函数,而是一个概率质量函数,其中每个观测值的质量是其相对频率。计算相对频率:

values, freqs = np.unique(data, return_counts=True)
rfreqs = freqs / data.size

这并不意味着数据是经验分布中的随机样本。如果您想仅通过查看数据就知道您的数据是哪个分布的样本(如果有的话),答案是您做不到。但这更多是关于统计而不是编程。

【讨论】:

感谢您的详细解释。我的数据是真实世界的 twitter 抓取关键字,关键字的频率对我来说看起来更谨慎。绘制 CDF 时,它显示的步骤多于曲线。【参考方案5】:

直方图并不像你想象的那样,你试图显示一个条形图。直方图需要列表中的每个数据点,而不是频率本身。你有 [3,2,0,4,...] 回合应该有 [1,1,1,2,2,4,4,4,4]。您无法自动确定概率分布

【讨论】:

我的数据本质上是谨慎的。因此我无法绘制直方图。但是,如果有人可以帮助提供正确的步骤或代码,我将不胜感激。上面有 5 个答案,我很困惑。 @SitzBlogz 你已经绘制了一个直方图,它向左显示了强烈的偏斜,在右侧显示了很长的尾巴。使用更多的垃圾箱可以提供更好的洞察力。 @Goyo 我想这就是我一直在寻找的人来告诉我我的阴谋,现在我知道非常感谢你:) 很高兴指出您刚刚复制了@Kobbe 的评论作为答案。另外,我不认为这是正确的。 OP 想知道 频率的分布,如果有三个标签,每个标签的频率为 1000...那么直方图应该显示 3不是总和(3000)。【参考方案6】:

我想你问的是一个稍微不同的问题:

我的原始数据和我映射到的曲线之间有什么相关性?

这是一个概念问题,您正在尝试理解值 R 和 R 平方的含义。首先通过this MiniTab blog post 工作。您可能想浏览此非 Python Kaledia Graph Guide 以了解要拟合的曲线类别以及最小均方在拟合曲线中的用法。

您可能被否决了,因为这是一道数学题,而不是编程题。

【讨论】:

感谢您的回答。我得到了更多的疑虑。我同意这可能更像是一个统计问题而不是编程问题。但我试图了解现实生活中离散数据的分布。 对一组真实数据,画散点图看看。为了使其自动化,请为每种类型使用您最喜欢的曲线拟合算法,例如不同的多项式并计算相关性。显示相关性最高的曲线类型。【参考方案7】:

我可能遗漏了一些东西,但似乎有一个要点被全面忽视了:您所描述的数据集是一个分类数据集。也就是说,x 值不是数字,它们只是单词(#Car、#photo 等)。概率分布形状的概念对于分类数据集没有意义,因为这些类别没有逻辑顺序。直方图甚至会是什么样子? #Car 会是第一个垃圾箱吗?或者它会一直在你的图表的右边吗?除非你有一些标准来量化你的类别,否则试图根据分布的形状做出判断是没有意义的。

这里有一个基于文本的小例子来说明我在说什么。假设我调查了一群人并询问他们最喜欢的颜色。我绘制结果:

   Red | ##
 Green | #####
  Blue | #######
Yellow | #####
Orange | ##

嗯,看起来颜色偏好是正态分布的。等等,如果我在图表中随机按不同的顺序排列颜色会怎样:

  Blue | #######
Yellow | #####
 Green | #####
Orange | ##
   Red | ##

我猜数据实际上是正偏态的?当然不是这样 - 对于分类数据集,分布的形状是没有意义的。只有当你决定如何量化数据集中的每个主题标签时,这个问题才会有意义。您想将主题标签的长度与其频率进行比较吗?还是主题标签的字母顺序与其频率?等等。

【讨论】:

数据是离散的,不会像任何现实世界的数据那样连续,我必须确定它是偏斜的还是正态的或什么样的分布。它与我们在第 1 列中的内容无关,因为它将是任何随机关键字或名称或任何重要的东西是第 2 列,我们有这些关键字的计数并将该计数放入某个函数中以查找概率分布功能和未来是将数据分类到某个类别中。如果我在这里没有错,您建议我对数据进行排序并绘制直方图,我也尝试过,但我无法得到它。 将此视为来自 Instagram 的数据,我们在其中发现太多#keywords,因此我试图确定这些关键字的 pdf 可能持续一天或其他时间。当我绘制 CDF 时,我得到的是步骤而不是平滑曲线。 @SitzBlogz 除了我在回答中提到的经验分布之外,您无法在数据中找到任何分布。您可以假设您的数据是其他分布的随机变量并对其进行测试,但这是另一回事。 @Goyo 我确实读过你关于经验的建议,这很有说服力,但如果你在这里看到所有这些建议,我有点困惑。 @SitzBlogz 您得到的答案令人困惑,因为您的问题有点令人困惑。所以你想“知道数据本身携带的分布是什么”?看我的回答。您想找到适合您数据的已知分布吗?我不清楚,这里有些人解释你这样做。你有计算/绘制直方图、kde 的问题吗?有一些暗示可能是这种情况,但它们非常模糊。答案可以和问题一样好,而且还有改进的余地。

以上是关于概率分布函数 Python的主要内容,如果未能解决你的问题,请参考以下文章

概率函数,分布函数,密度函数

已知分布函数如下,求概率密度,请写出具体步骤

概率分布函数和概率密度函数

概率分布函数和概率密度函数

Python中是否有一个函数可以根据概率分布给出输出?

概率分布之间的距离度量以及python实现