将函数应用于 pandas groupby 和索引
Apply functions to pandas groupby and indexing
我试图理解 Pandas Groupby,但我目前看到一些我不理解的行为。基本上,我有一个看起来像(只显示头部)的数据集:
userId movieId rating timestamp parsed_time
0 1 2 3.5 1112486027 2005-04-02 23:53:47
1 1 29 3.5 1112484676 2005-04-02 23:31:16
2 1 32 3.5 1112484819 2005-04-02 23:33:39
3 1 47 3.5 1112484727 2005-04-02 23:32:07
4 1 50 3.5 1112484580 2005-04-02 23:29:40
我检查了数据集的 NaN/null 个值,有 none 个。现在,我想计算每部电影的平均评分,以及标准偏差。
获得平均评分很简单:
ratings = pd.read_csv('ratings.csv', sep=',')
average_rating = ratings[['movieId','rating']].groupby('movieId',as_index=False).mean()
average_ratings.rename(columns={'rating':'AverageRating'}, inplace=True)
这给了我类似的东西:
movieId AverageRating
0 1 3.921240
1 2 3.211977
2 3 3.151040
3 4 2.861393
4 5 3.064592
所以这一切都很好,这也是我对 groupby()
和 mean()
组合的期望。
现在,我想做同样的事情来计算电影评级的标准偏差,并将其作为新列添加到 average_rating
df:
average_rating['StdDev'] = ratings[['movieId','rating']].groupby('movieId').std()
这给了我:
movieId AverageRating StdDev
0 1 3.921240 NaN
1 2 3.211977 0.889012
2 3 3.151040 0.951150
3 4 2.861393 1.006642
4 5 3.064592 1.095702
这里让我感到困惑的是,作为第一个条目出现在我的 StdDev 列中的 NaN。如果我手动提取行,比如 movieId [1,2] 并计算那些的均值和标准差:
print('Mean movieID 1:')
print(ratings[ratings['movieId']==1]['rating'].mean())
print('StdDev movieID 1:')
print(ratings[ratings['movieId']==1]['rating'].std())
print('Mean movieID:')
print(ratings[ratings['movieId']==2]['rating'].mean())
print('StdDev movieID 2:')
print(ratings[ratings['movieId']==2]['rating'].std())
我被退回了:
Mean movieID 1:
3.921240
StdDev movieID 1:
0.889012
Mean movieID 2:
3.211977
StdDev movieID 2:
0.951150
所以在我看来,groupby.std()
出于某种原因似乎跳过了第一个索引,将其替换为 NaN,然后填写正确的值,但移动了一个索引。我不理解这种行为,这不是我所期望的。谁能向我解释第二次使用 groupby 时的这种行为,以及如何避免 it/get 它做我想做的事?
问题不是在计算标准差时发生,而是在将结果分配给新列时发生StdDev
。这是因为 pandas 隐含地按索引进行赋值。
下面的代码应该可以工作,因为两个 groupby
操作的结果都在 movieId
上建立了索引:
# note how I remove as_index=False
average_rating = ratings[['movieId','rating']].groupby('movieId').mean()
average_rating['StdDev'] = ratings[['movieId','rating']].groupby('movieId').std()
当然,你应该同时做这两件事:
ratings[['movieId','rating']].groupby('movieId').agg(['mean', 'std'])
更优雅(或至少更标准):
ratings.groupby('movieId')['rating'].agg(['mean', 'std'])
这里的关键是,在你的第一个groupby中,你包含了as_index=False
,所以创建的df有一个新的序列索引。在您的 secong groupby 中,您不包含 as_index
参数,因此它使用 MovieID 作为索引。
当您随后将其分配为 average_ratings
中的列时,索引不是指同一事物。
在这种情况下,看起来您的索引已移动,因为您有 MovieID 1-5 和整数索引 0-4。 StdDev 列中的空值仅反映了没有 ID = 0 的电影这一事实。
我试图理解 Pandas Groupby,但我目前看到一些我不理解的行为。基本上,我有一个看起来像(只显示头部)的数据集:
userId movieId rating timestamp parsed_time
0 1 2 3.5 1112486027 2005-04-02 23:53:47
1 1 29 3.5 1112484676 2005-04-02 23:31:16
2 1 32 3.5 1112484819 2005-04-02 23:33:39
3 1 47 3.5 1112484727 2005-04-02 23:32:07
4 1 50 3.5 1112484580 2005-04-02 23:29:40
我检查了数据集的 NaN/null 个值,有 none 个。现在,我想计算每部电影的平均评分,以及标准偏差。
获得平均评分很简单:
ratings = pd.read_csv('ratings.csv', sep=',')
average_rating = ratings[['movieId','rating']].groupby('movieId',as_index=False).mean()
average_ratings.rename(columns={'rating':'AverageRating'}, inplace=True)
这给了我类似的东西:
movieId AverageRating
0 1 3.921240
1 2 3.211977
2 3 3.151040
3 4 2.861393
4 5 3.064592
所以这一切都很好,这也是我对 groupby()
和 mean()
组合的期望。
现在,我想做同样的事情来计算电影评级的标准偏差,并将其作为新列添加到 average_rating
df:
average_rating['StdDev'] = ratings[['movieId','rating']].groupby('movieId').std()
这给了我:
movieId AverageRating StdDev
0 1 3.921240 NaN
1 2 3.211977 0.889012
2 3 3.151040 0.951150
3 4 2.861393 1.006642
4 5 3.064592 1.095702
这里让我感到困惑的是,作为第一个条目出现在我的 StdDev 列中的 NaN。如果我手动提取行,比如 movieId [1,2] 并计算那些的均值和标准差:
print('Mean movieID 1:')
print(ratings[ratings['movieId']==1]['rating'].mean())
print('StdDev movieID 1:')
print(ratings[ratings['movieId']==1]['rating'].std())
print('Mean movieID:')
print(ratings[ratings['movieId']==2]['rating'].mean())
print('StdDev movieID 2:')
print(ratings[ratings['movieId']==2]['rating'].std())
我被退回了:
Mean movieID 1:
3.921240
StdDev movieID 1:
0.889012
Mean movieID 2:
3.211977
StdDev movieID 2:
0.951150
所以在我看来,groupby.std()
出于某种原因似乎跳过了第一个索引,将其替换为 NaN,然后填写正确的值,但移动了一个索引。我不理解这种行为,这不是我所期望的。谁能向我解释第二次使用 groupby 时的这种行为,以及如何避免 it/get 它做我想做的事?
问题不是在计算标准差时发生,而是在将结果分配给新列时发生StdDev
。这是因为 pandas 隐含地按索引进行赋值。
下面的代码应该可以工作,因为两个 groupby
操作的结果都在 movieId
上建立了索引:
# note how I remove as_index=False
average_rating = ratings[['movieId','rating']].groupby('movieId').mean()
average_rating['StdDev'] = ratings[['movieId','rating']].groupby('movieId').std()
当然,你应该同时做这两件事:
ratings[['movieId','rating']].groupby('movieId').agg(['mean', 'std'])
更优雅(或至少更标准):
ratings.groupby('movieId')['rating'].agg(['mean', 'std'])
这里的关键是,在你的第一个groupby中,你包含了as_index=False
,所以创建的df有一个新的序列索引。在您的 secong groupby 中,您不包含 as_index
参数,因此它使用 MovieID 作为索引。
当您随后将其分配为 average_ratings
中的列时,索引不是指同一事物。
在这种情况下,看起来您的索引已移动,因为您有 MovieID 1-5 和整数索引 0-4。 StdDev 列中的空值仅反映了没有 ID = 0 的电影这一事实。