2017-02-14 86 views
0

我有以下形式的數據幀:大熊貓的GroupBy聚集只有一列

>>> sales = pd.DataFrame({'seller_id':list('AAAABBBB'),'buyer_id':list('CCDECDEF'),\ 
          'amount':np.random.randint(10,20,size=(8,))}) 
>>> sales = sales[['seller_id','buyer_id','amount']] 
>>> sales 
    seller_id buyer_id amount 
0   A  C  18 
1   A  C  15 
2   A  D  11 
3   A  E  12 
4   B  C  16 
5   B  D  18 
6   B  E  16 
7   B  F  19 

現在我想做的是每個賣家計算其最大的買家佔據總銷售金額的份額。我有這樣做的代碼,但我必須不斷重置索引和分組,這是浪費。一定有更好的方法。我想要一個解決方案,我可以一次聚合一列,並保持其他人分組。 這裏是我當前的代碼:

>>> gr2 = sales.groupby(['buyer_id','seller_id']) 
>>> seller_buyer_level = gr2['amount'].sum() # sum over different purchases 
>>> seller_buyer_level_reset = seller_buyer_level.reset_index('buyer_id') 
>>> gr3 = seller_buyer_level_reset.groupby(seller_buyer_level_reset.index) 
>>> result = gr3['amount'].max()/gr3['amount'].sum() 

>>> result 
seller_id 
A 0.589286 
B 0.275362 

我簡化了一下。實際上,我也有一個時間段列,所以我想在賣家和時間段級別這樣做,這就是爲什麼在gr3中我按多索引進行分組(在本例中,它顯示爲單個索引) 。 我認爲會有一個解決方案,而不是減少和重組,我將能夠聚集只有一個索引出組,但其他人分組,但無法在文檔或在線找到它。有任何想法嗎?

回答

0

這裏是一個一行,但它一旦復位指數,太:

sales.groupby(['seller_id','buyer_id']).sum().\ 
    reset_index(level=1).groupby(level=0).\ 
    apply(lambda x: x.amount.max()/x.amount.sum()) 
#seller_id 
#A 0.509091 
#B 0.316667 
#dtype: float64 
+0

謝謝!我想問題是,如果groupby(level = 0)很快就是因爲它是索引。如果是,那麼這是一個完美的答案。 – ErnestScribbler

+0

我定時你的原始解決方案和我的。你的速度提高了30%。所以,我猜,我的不值得。 – DyZ

+0

我也計時了。我認爲這只是「減速」的「適用」線。 – ErnestScribbler

0

我會用這個和pivot_table然後做廣播(見What does the term "broadcasting" mean in Pandas documentation?)。

首先,與索引seller_idbuyer_id樞轉中的數據列:

sales_pivot = sales.pivot_table(index='seller_id', columns='buyer_id', values='amount', aggfunc='sum') 

然後,通過的總和除以每行中的值,所述行:

result = sales_pivot.div(sales_pivot.sum(axis=1), axis=0) 

最後,您可以撥打result.max(axis=1)查看每位賣家的最高份額。

+0

謝謝!但是,這會創建一個大小爲n_buyers * n_sellers的表格,這可能適用於這個玩具示例,但在我的真實數據集中永遠不會適應內存。 – ErnestScribbler