计算两个数据帧的平均值

Computing averages from two dataframes

一个数据框看起来像这样(这些只是小样本):

user    item     rating
u1      i1       0
u1      i2       1
u1      i3       1
u2      i2       1
u2      i3       0
u2      i4       0
u2      i5       0
u3      i6       1
u3      i7       1
u4      i4       1
u4      i7       0

还有一个是这样的:

item     property_1    ...   property_n    grade
i1       0.60                1             Bad
i2       0.90                1             Good
i3       0.90                0             Good
i4       0.75                1             Bad

可能有些项目在第一个数据框中而不在第二个数据框中,反之亦然。

我想知道的是不好的东西是不是真的差评,好的东西是不是真的好评。我知道我可以得到平均分item 评价如下:

df.groupby(['item'])['rating'].mean()

如果我为 user 这样做,我会得到该用户给出的平均评分。

但是我怎样才能构建如下所示的数据框?

item      average_rating      grade
i1                    0         Bad
i2                    1        Good
i3                  0.5        Good
i4                  0.5         Bad

一个额外的问题:我如何合并 有关用户 的信息? (也许一个用户给出了很多 0 评论,但你不能责怪他们,因为这些项目也被认为是坏的,但另一个用户对被认为好的项目给出了很多差评)。但并非所有项目都在第二个数据框中,我们不知道用户的评论是否与等级一致(可能他们对 5 个坏项目的评价很好,对 5 个好项目的评价很差)。所以我会改为将项目等级转换为 01:

user       reviews_given           item_grades       consistency
u1               [0,1,1]               [0,1,1]              1.00
u80            [0,1,0,1]             [1,0,1,0]              0.00

这样的列表有用吗?这怎么可能?

第一个问题:您可以使用 df.merge() 对两个表进行合并(如 SQL 连接)。

df_group = df.groupby(['item']).mean() # notice i don't have the ['rating'] piece in here. that makes this a series, but we want a dataframe to do the merge
df_group.merge(df2[['item','grade']],on='item') # i just pull from df2 the two columns that I need
    item    rating  grade
0   i1      0.0     Bad
1   i2      1.0     Good
2   i3      0.5     Good
3   i4      0.5     Bad

对第二个问题:也可以用merge,加上一些其他的东西。

下面我认为 df 是您发布的第一个 table 和 df2 您发布的第二个。

df3 = df.merge(df2[['item','grade']],on='item') # similar to above, but we haven't grouped yet and still have user
df3['grade'] = df3['grade'].map({'Bad':0,'Good':1}) # convert grades to numbers
df3['match?'] = (df3['rating'] == df3['grade']).map({True:1,False:0}) # new column that returns 1 if the rating and grade match, 0 if don't match
df4 = df3.groupby('user').agg({'rating':list,'grade':list,'match?':list,'match?':'mean'}) # a new dataframe that groups the last one but groups a few columns into lists and also gets a mean of matches
df4
         rating      grade    match?
user
u1    [0, 1, 1]  [0, 1, 1]  1.000000
u2    [1, 0, 0]  [1, 1, 0]  0.666667
u4          [1]        [0]  0.000000
>>>