在项目字典中的每个项目上拟合贝塔分布



我有一个字典,里面有唯一的ID和[分数的样本分布]对,例如:"100":[0.5,0.6,0.2,0.7,0.3]。数组的长度并不完全相同。

对于我字典中的每个项目/"核心"数组,我想在分数分布上拟合一个beta分布,如scipy.stats.beta.fit((,并获得每个样本的alpha/beta参数。然后我想把它放在一本新字典里——所以它会像"101":(1.5,1.8(

我知道我可以通过用for循环迭代我的字典来做到这一点,但字典相当庞大/我想知道是否有更有效的计算方法。

对于上下文,我获取该字典的方式是从pandas数据帧中获取,我在其中这样做:

my_dictionary = df.groupby('unique_id')['score'].apply(list).to_dict()

df看起来像这样:

例如:

df = pd.DataFrame({
'id': ['100', '100', '100', '101', '101', '102'],
'score' : [0.5, 0.3, 0.2, 1, 0.2, 0.9]
})

然后生成的字典看起来像:

{'100': [0.5, 0.3, 0.2], '101': [0.2, 0.1], '102': [0.9]}

是否还有一种方法可以直接从df.groupby级别拟合beta分布,而不必先将其转换为字典,然后用scipy在字典上循环?我能做些什么吗:

df.groupby('unique_id')['score'].apply(stats.beta.fit()).to_dict()

或者类似的东西?

试试这个:

df=df.groupby('id').apply(lambda x: list(beta.fit(x.score)))
dc=df.to_dict()

输出:

df
id
100    [0.2626434905176847, 0.37866242902872393, 0.18...
101    [1.253982875508286, 0.8832540117966552, -0.093...
102    [1.044551187075241, 1.0167687597781938, 0.8999...
dtype: object
dc
{'100': [0.2626434905176847, 0.37866242902872393, 0.18487097639113187, 0.3151290236088682], 
'101': [1.253982875508286, 0.8832540117966552, -0.09383386122371801, 1.0938338612237182], 
'102': [1.044551187075241, 1.0167687597781938, 0.8999999999999999, 1.1272504901983386e-16]}

正如我所认识到的,每行数据帧df:需要适应多个贝塔系数

df['beta_fit'] = df['score'].apply( lambda x: stats.beta.fit(x))

现在结果存储在df['beta_fit']:中

0    (0.5158954356434775, 0.4824876600627905, 0.154...
1    (0.18219650169013427, 0.18228236200252418, 0.1...
2    (2.874609362944296, 0.8497751096020354, -0.341...
3    (1.313976940871222, 0.5956397575363881, -0.093...
Name: beta_fit, dtype: object

如果要保持位置(loc(和比例(scale(固定,则需要在scipy.stats.beta.fit中指出这一点。您可以使用functools.partial进行以下操作:

import pandas as pd
>>> import scipy.stats
>>> from functools import partial
>>> df = pd.DataFrame({
...         'id': ['100', '100', '100', '101', '101', '102'],
...         'score' : [0.5, 0.3, 0.2, 0.1, 0.2, 0.9]
...     })
>>> beta = partial(scipy.stats.beta.fit, floc=0, fscale=1)
>>> df.groupby('id')['score'].apply(beta)
id
100      (4.82261025047374, 9.616623800842953, 0, 1)
101    (0.7079910251948778, 0.910200073771759, 0, 1)
Name: score, dtype: object

请注意,我已经调整了您的输入示例,因为它包含不正确的值(1.0(,而且在某些情况下,值太少,无法成功拟合。

最新更新