数据框中的贝叶斯平均
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:
- 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 的方式的问题?或者有没有更简单的方法来处理这个问题(例如预先存在的 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)
接下来,我发现最直接的方法是将贝叶斯平均方程的每个变量创建为数据框中的一列或独立变量:
计算每个柱的 v
值:
df['v'] = df[user_cols].count(axis=1)
计算 m
的值(在本例中等于 2.0):
m = np.mean(df['v'])
计算每个柱的 w
值:
df['w'] = df['v']/(df['v'] + m)
并计算每个柱的 R
值:
df['R'] = np.mean(df[user_cols], axis=1)
最后得到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 分数。如果需要,您可以删除 v
、w
和 R
临时列: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
我正在尝试基于数据帧(按行)提取一系列贝叶斯平均值。
例如,假设我有一系列(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:
- 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 的方式的问题?或者有没有更简单的方法来处理这个问题(例如预先存在的 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)
接下来,我发现最直接的方法是将贝叶斯平均方程的每个变量创建为数据框中的一列或独立变量:
计算每个柱的
v
值:df['v'] = df[user_cols].count(axis=1)
计算
m
的值(在本例中等于 2.0):m = np.mean(df['v'])
计算每个柱的
w
值:df['w'] = df['v']/(df['v'] + m)
并计算每个柱的
R
值:df['R'] = np.mean(df[user_cols], axis=1)
最后得到
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 分数。如果需要,您可以删除 v
、w
和 R
临时列: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