![](/img/trans.png)
[英]Plotting the PMF of the Poission Distribution of Columns from a csv Dataframe
[英]Poission Distribution considering time left
我想计算在n
分钟的足球比赛中每个结果的剩余概率。
在这种情况下,我预计70
分钟时主队的进球数为2.69
,客队的进球数为1.12
,目前的结果是2-1
代码
from scipy.stats import poisson
from itertools import product
import numpy as np
import pandas as pd
xgh = 2.69
xga = 1.12
minute = 70
hg, ag = 2,1
phs=[]
pas=[]
for i, l in zip(range(0, 6), range(0, 6)):
ph = poisson.pmf(mu=xgh, k=i, loc=hg)
phs.append(ph)
pa = poisson.pmf(mu=xga, k=l, loc=ag)
pas.append(pa)
prod_table = np.array([(i*j) for i, j in product(phs, pas)])
prod_table.shape = (6, 6)
prob_df = pd.DataFrame(prod_table, index=range(0,6), columns=range(0, 6))
这返回2-1
最终结果的概率为2.21%
,这是相当低的,考虑到只剩下20
分钟,我预计概率很高
泊松分布是一个事件在给定时间范围内发生 k 次的概率,已知该事件平均应该在同一时间范围内发生 μ 次。
泊松分布的假设是事件是完全独立的。 所以它已经发生了多少次是没有意义的。 并且它们是均匀分布的(如果我可以使用这个令人困惑的词,因为这不是均匀分布)。
大多数时候,泊松的用途是计算 k 个事件在时间帧 T 内发生的概率,当我们知道 μ 个事件平均发生在时间帧 τ 内(与第 1 句话的区别在于 T 和 τ 不相同)。
但这是容易的部分:因为事件是均匀分布的,如果 μ 事件平均发生在时间范围 τ 内,那么 μ×T/τ 事件平均应该发生在时间范围 T 内(理解:如果我们要实验数百万个时间帧 T,那么平均而言,每个时间帧中应该有 μT/τ 事件)。
因此,要计算事件在时间帧 T 中发生 k 次的概率,知道它在时间帧 τ 中发生 μ 次,您只需回答问题“事件在时间帧 T 中发生了多少次 k 次,知道它在该时间范围内发生 μT/τ 次”。 这是泊松可以回答的问题。
在 python 中,答案是poisson.pmf(k, μT/τ)
。
在您的情况下,您知道 μ,即 90 分钟时间范围内预期的目标数量。 你知道剩下的得分时间是 20 分钟。 如果在 90 分钟的时间范围内预计有 2.69 个进球,那么在 20 分钟的时间范围内预计会有 0.5978 个进球(至少,泊松假设事情是这样进行的)。 因此,该团队在该时间范围内没有进球的概率是poisson.pmf(0, 0.5978)
。 或者,使用您的关键字样式poisson.pmf(mu=0.5978, k=0)
。 或者使用loc
,使目标poisson.pmf(mu=0.5978, k=2, loc=2)
(但这只是装饰性的。有一个 loc 参数只需用k-loc
替换 k )
因此,长话短说,您只需要按比例缩小xgh
和xga
,以便它们反映剩余时间内的预期目标数量。
for i, l in zip(range(0, 6), range(0, 6)):
ph = poisson.pmf(mu=xgh*(90-minute)/90, k=i, loc=hg)
phs.append(ph)
pa = poisson.pmf(mu=xga*(90-minute)/90, k=l, loc=ag)
pas.append(pa)
在此期间,由于有一个python
标签,对代码进行了一些评论
for i, l in zip(range(0, 6), range(0, 6)):
print(i,l)
产生
0 0
1 1
2 2
3 3
4 4
5 5
所以不使用单个变量是很奇怪的。 特别是如果你认为你无法使用不同的范围( zip
必须与相同长度的迭代一起使用。我们不知道在什么情况下,我们需要,例如, i 从 0 增长到 5 , 而 l 将从 0 增长到 10)
所以就
for k in range(0, 6):
ph = poisson.pmf(mu=xgh*(90-minute)/90, k=k, loc=hg)
phs.append(ph)
pa = poisson.pmf(mu=xga*(90-minute)/90, k=k, loc=ag)
pas.append(pa)
我推测,特别是因为下一个评论的 object 是什么,曾几何时,在您意识到这是多次计算完全相同的pmf
之前,有一个product
而不是那个zip
。
product 的使用可能已经简化为计算所有i,j
的phs[i]×pas[j]
的任务。 这是product
的一个很好的用法。
但是,由于您有 2 个 arrays,并且您打算从这些phs[i]×pas[j]
构建一个 numpy 数组,所以让 numpy 来完成这项工作。 它会更有效率。
prod_table = np.array(phs).reshape(-1,1)*np.array(pas)
这导致了另一个优化。 如果目标是将phs
和pha
转换为 arrays,以便我们可以将它们相乘(一个作为行,另一个作为列)得到表格,为什么不让 numpy 直接构建该数组。 和 numpy function 一样, pmf
可以让 k 是一个列表而不是标量,然后返回一个列表而不是标量。
所以
phs=poisson.pmf(mu=xgh*(90-minute)/90, k=range(6), loc=hg)
pas=poisson.pmf(mu=xga*(90-minute)/90, k=range(6), loc=ag)
所以,一共
prod_table=poisson.pmf(mu=xgh*(90-minute)/90, k=range(6), loc=hg).reshape(-1,1)*poisson.pmf(mu=xga*(90-minute)/90, k=range(6), loc=ag)
优化 | 时间(微秒) |
---|---|
没有 | 1647 微秒 |
和 | 329微秒 |
因此,它不仅是最紧凑和可读的。 它也(几乎正好)快了 5 倍。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.