2017-08-29 111 views
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 

我已經檢查楠/空值的數據集,以及有沒有。現在,我想計算每部電影的平均評分以及標準偏差。

獲得的平均評級是簡單的:

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 

我在這裏困惑的是NaN,它出現在我的StdDev專欄中的第一個條目。如果我提取手動行,說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時向我解釋這種行爲,以及如何避免它/讓它做我想要的?

回答

2

在計算標準偏差時不會發生問題,但將結果分配給新列StdDev時。這是因爲大熊貓的含義是隱含的。

下面的代碼應該工作,因爲這兩個groupby操作的結果被收錄在movieId

ratings[['movieId','rating']].groupby('movieId').agg(['mean', 'std']) 

更優雅(或:

# 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.groupby('movieId')['rating'].agg(['mean', 'std']) 
+0

謝謝,此解決方案完成了這項工作。我讚賞你提出的更優雅的解決方案。雙'agg()'真的很方便,我不知道這是可能的 –

+0

後續問題;包含'as_index = False'的原因是我需要隨後將其與另一個df合併,該函數也具有'movieId'作爲關鍵字,所以我想在'movieId'上進行合併。我試圖在你的最後一個例子中插入'as_index = False',但是仍然使用'movieId'作爲最終df中的索引(這也讓我感到困惑)。 –

+0

我同意,這很令人驚訝,但'as_index = False'不適用於'agg'。這裏最好的解決方案是用'.reset_index()'結束。 – IanS

2

這裏的關鍵我在你的第一個groupby中,你包含了as_index=False,所以創建的df有一個新的序列索引。在你的second groupby中,你不包含as_index參數,所以它使用MovieID作爲索引。

然後,當您將其指定爲average_ratings中的一列時,索引不會引用相同的內容。

在這種情況下恰好如此,它看起來像您的索引已被移位,因爲您具有MovieID 1-5和一個整數索引0-4。 StdDev列中的空值僅僅反映了沒有ID = 0的電影的事實。

+0

這是一個很好的解釋,謝謝你提供了groupby的細節,我知道我錯過了一些簡單的東西! –