2016-02-20 21 views
2

大熊貓數據框中有一個熊貓數據幀像下面我如何GROUPBY一些條件

buyer_id item_id order_id  date 
    139  57  387  2015-12-28 
    140  9  388  2015-12-28 
    140  57  389  2015-12-28 
    36  9  390  2015-12-28 
    64  49  404  2015-12-29 
    146  49  405  2015-12-29 
    81  49  406  2015-12-29 
    140  80  407  2015-12-30 
    139  81  408  2015-12-30 

有很多上述數據幀的行。我試圖實現的是,是否推出新菜餚,以推動我的用戶迴歸。 item_id被映射到一個菜名。我想看到的是如果特定用戶在不同的日子訂購不同的菜餚。 如buyer_id 140 has ordered two dishes item_id (9,57) on 28th Dec and same buyer has ordered different dish (item_id = 80) on 30th Dec 然後我想將此用戶爲1

如何我在Python中就是這個樣子

item_wise_order.groupby(['date','buyer_id'])['item_id'].apply(lambda x:  
x.tolist()) 

它給了我下面的輸出

date  buyer_id 
2015-12-28 139     [57] 
      140     [9,57]  
      36     [9] 
2015-12-29 64     [49] 
      146     [49] 
      81     [49] 
2015-12-30 140     [80] 
      139     [81] 

所需的輸出

buyer_id item_id order_id  date flag 
    139  57  387  2015-12-28  1 
    140  9  388  2015-12-28  1 
    140  57  389  2015-12-28  1 
    36  9  390  2015-12-28  0 
    64  49  404  2015-12-29  0 
    146  49  405  2015-12-29  0 
    81  49  406  2015-12-29  0 
    140  80  407  2015-12-30  1 
    139  81  408  2015-12-30  1 
+0

您希望的輸出是什麼? –

+0

@AntonProtopopov我編輯了問題 – Neil

+0

爲什麼預期輸出中第一行的標誌不是1? –

回答

2

類似安東的回答,但使用申請

users = df.groupby('buyer_id').apply(lambda r: r['item_id'].unique().shape[0] > 1 and 
               r['date'].unique().shape[0] > 1)*1 
df.set_index('buyer_id', inplace=True) 
df['good_user'] = users 

結果:

  item_id order_id  date good_user 
buyer_id 
139   57  387 2015-12-28   1 
140    9  388 2015-12-28   1 
140   57  389 2015-12-28   1 
36    9  390 2015-12-28   0 
64    49  404 2015-12-29   0 
146   49  405 2015-12-29   0 
81    49  406 2015-12-29   0 
140   80  407 2015-12-30   1 
139   81  408 2015-12-30   1 

編輯因爲我想到了另一種情況:假設數據顯示買方在兩天內購買相同的兩件(或更多)商品。該用戶是否應被標記爲1或0?因爲實際上,他/她實際上並沒有在第二天選擇任何不同的東西。 所以買下表中的買家81。你看他們在這兩個日期只買49和50。

buyer_id item_id order_id date 
     139  57  387 2015-12-28 
     140   9  388 2015-12-28 
     140  57  389 2015-12-28 
      36   9  390 2015-12-28 
      64  49  404 2015-12-29 
     146  49  405 2015-12-29 
      81  49  406 2015-12-29 
     140  80  407 2015-12-30 
     139  81  408 2015-12-30 
      81  50  406 2015-12-29 
      81  49  999 2015-12-30 
      81  50  999 2015-12-30 

,以適應這一點,這就是我想出了(有點難看,但應該工作)

# this function is applied to all buyers 
def find_good_buyers(buyer): 
    # which dates the buyer has made a purchase 
    buyer_dates = buyer.groupby('date') 
    # a string representing the unique items purchased at each date 
    items_on_date = buyer_dates.agg({'item_id': lambda x: '-'.join(x.unique())}) 
    # if there is more than 1 combination of item_id, then it means that 
    # the buyer has purchased different things in different dates 
    # so this buyer must be flagged to 1 
    good_buyer = (len(items_on_date.groupby('item_id').groups) > 1) * 1 
    return good_buyer 


df['item_id'] = df['item_id'].astype('S') 
buyers = df.groupby('buyer_id') 

good_buyer = buyers.apply(find_good_buyers) 
df.set_index('buyer_id', inplace=True) 
df['good_buyer'] = good_buyer 
df.reset_index(inplace=True) 

這適用於買方81日起,將其設置爲0,因爲一旦你組,兩個日期購買的商品將具有相同的「49-50」商品組合,因此組合數量= 1,買方將被標記爲0.

+0

非常感謝你的回答。但是,只有當在不同的日期有不同的'item_id'時,該標誌才應該設置爲true – Neil

+0

如何設置標誌爲'0&1'我不想將索引設置爲'buyer_id' – Neil

+0

我更新了答案得到0和1.(只需將布爾列乘以1強制爲0/1) 1的條件是超過2個日期購買的商品超過2個。即如果買方只出現在1日期或者買方只買一件東西,它就不能設置爲1。這不包括你的情況?您在此處顯示的數據不會顯示其他情況 – mkln

1

Yo你可以groupby buyer_id,然後聚合列np.unique。然後,您將獲得np.ndarrays用於有幾個日期和item_id的行。你可以找到的isinstance行,你會得到bool系列,你可以傳遞給聚合數據框並找到感興趣的買家。從第一和第二步驟

df_agg = df.groupby('buyer_id')[['date', 'item_id']].agg(np.unique) 
df_agg = df_agg.applymap(lambda x: isinstance(x, np.ndarray)) 

buyers = df_agg[(df_agg['date']) & (df_agg['item_id'])].index 
mask = df['buyer_id'].isin(buyers) 

df['flag'] = 0 
df.loc[mask, 'flag'] = 1 

In [124]: df 
Out[124]: 
    buyer_id item_id order_id  date flag 
0  139  57  387 2015-12-28  1 
1  140  9  388 2015-12-28  1 
2  140  57  389 2015-12-28  1 
3  36  9  390 2015-12-28  0 
4  64  49  404 2015-12-29  0 
5  146  49  405 2015-12-29  0 
6  81  49  406 2015-12-29  0 
7  140  80  407 2015-12-30  1 
8  139  81  408 2015-12-30  1 

輸出:通過與獲得buyers過濾原始數據框,你可以填寫flag行與loc

In [146]: df.groupby('buyer_id')[['date', 'item_id']].agg(np.unique) 
Out[146]: 
           date  item_id 
buyer_id          
36      2015-12-28   9 
64      2015-12-29   49 
81      2015-12-29   49 
139  [2015-12-28, 2015-12-30]  [57, 81] 
140  [2015-12-28, 2015-12-30] [9, 57, 80] 
146      2015-12-29   49 

In [148]: df_agg.applymap(lambda x: isinstance(x, np.ndarray)) 
Out[148]: 
      date item_id 
buyer_id    
36  False False 
64  False False 
81  False False 
139  True True 
140  True True 
146  False False 
+0

非常感謝你的回答.. Appriciated :) – Neil

+0

你在哪裏檢查不同'item_id'的代碼中的條件? – Neil

+0

@nil與'np一起使用'agg'。unique'。如果有多個唯一的'item_id',那麼它將是'np.ndarray',它會給'isinstance(x,np.ndarray)''True'' –