数据框中的贝叶斯平均

Bayesian Averaging in a Dataframe

我正在尝试基于数据帧(按行)提取一系列贝叶斯平均值。

例如,假设我有一系列(0 到 1)用户对糖果的评分,存储在数据框中,如下所示:

            User1   User2   User3
Snickers    0.01    NaN     0.7
Mars Bars   0.25    0.4     0.1
Milky Way   0.9     1.0     NaN
Almond Joy  NaN     NaN     NaN
Babe Ruth   0.5     0.1     0.3

我想在不同的 DF 中创建一个列,它代表上述数据中每个糖果条的贝叶斯平均值。

为了计算 BA,我使用 equation presented here:

我已经将其翻译成 python:

def bayesian_average(df):
    """given a dataframe, returns a series of bayesian averages"""
    R = df.mean(axis=1)
    C = df.sum(axis=1).sum()/df.count(axis=1).sum()
    w = df.count(axis=1)/(df.count(axis=1)+(df.count(axis=1).sum()/len(df.dropna(how='all', inplace=False))))
    return ((w*R) + ((1-w)*C))

other_df['bayesian_avg'] = bayesian_average(ratings_df)

但是,我的计算似乎不正确,随着初始数据框中用户列数量的增加,最终计算出的贝叶斯平均值也会增加(大于 1 的数字)。

这是我使用的基本方程式的问题,还是我将其转换为 python 的方式的问题?或者有没有更简单的方法来处理这个问题(例如预先存在的 package/function)?

谢谢!

我以您给出的数据框为例:

d = {
    'Bar': ['Snickers', 'Mars Bars', 'Milky Way', 'Almond Joy', 'Babe Ruth'],
    'User1': [0.01, 0.25, 0.9, np.nan, 0.5],
    'User2': [np.nan, 0.4, 1.0, np.nan, 0.1],
    'User3': [0.7, 0.1, np.nan, np.nan, 0.3]
}

df = pd.DataFrame(data=d)

看起来像这样:

    Bar         User1   User2    User3
0   Snickers     0.01     NaN      0.7
1   Mars Bars    0.25     0.4      0.1
2   Milky Way    0.90     1.0      NaN
3   Almond Joy    NaN     NaN      NaN
4   Babe Ruth    0.50     0.1      0.3

我做的第一件事是创建一个包含所有有用户评论的列的列表:

user_cols = []
for col in df.columns.values:
    if 'User' in col:
        user_cols.append(col)

接下来,我发现最直接的方法是将贝叶斯平均方程的每个变量创建为数据框中的一列或独立变量:

  1. 计算每个柱的 v 值:

    df['v'] = df[user_cols].count(axis=1)

  2. 计算 m 的值(在本例中等于 2.0):

    m = np.mean(df['v'])

  3. 计算每个柱的 w 值:

    df['w'] = df['v']/(df['v'] + m)

  4. 并计算每个柱的 R 值:

    df['R'] = np.mean(df[user_cols], axis=1)

  5. 最后得到C的值(本例中等于0.426):

    C = np.nanmean(df[user_cols].values.flatten())

现在我们已准备好计算每个糖果的贝叶斯平均得分 S

df['S'] = df['w']*df['R'] + (1 - df['w'])*C

这为我们提供了一个如下所示的数据框:

    Bar        User1    User2    User3   v    w      R       S
0   Snickers    0.01      NaN      0.7   2  0.5  0.355  0.3905
1   Mars Bars   0.25      0.4      0.1   3  0.6  0.250  0.3204
2   Milky Way   0.90      1.0      NaN   2  0.5  0.950  0.6880
3   Almond Joy  NaN       NaN      NaN   0  0.0    NaN     NaN
4   Babe Ruth   0.50      0.1      0.3   3  0.6  0.300  0.3504

最后一列 S 包含糖果的所有 S 分数。如果需要,您可以删除 vwR 临时列:df = df.drop(['v', 'w', 'R'], axis=1):

    Bar        User1    User2    User3        S
0   Snickers    0.01      NaN      0.7   0.3905
1   Mars Bars   0.25      0.4      0.1   0.3204
2   Milky Way   0.90      1.0      NaN   0.6880
3   Almond Joy  NaN       NaN      NaN      NaN
4   Babe Ruth   0.50      0.1      0.3   0.3504