数据框中的贝叶斯平均

时间:2019-01-25 00:16:04

标签: python pandas dataframe bayesian

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

例如,假设我有一系列(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

Bayesian Average

  • S =直板得分
  • R =直板用户评分的平均值
  • C =所有直板的平均用户评分
  • w =分配给R的权重,并计算为v /(v + m),其中v是该直板的用户评分数量,m是所有直板的平均评论数量。

我已经将其翻译成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的问题?还是有一种更简单的方法来处理此问题(例如,预先存在的软件包/功能)?

谢谢!

1 个答案:

答案 0 :(得分:2)

我从您作为示例给出的数据帧开始:

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