[英]groupby with conditions and classify python
我有 dataframe 有 2 列(名稱和 ID)。 有成千上萬的名字。 但是每個名字,只有兩個id(90和91,所以id列只包含90和91)。
樣品 dataframe如下所示。
name id
kevin 90
kevin 91
kevin 90
kevin 90
John 90
John 90
John 90
John 90
John 90
kevin 90
kevin 90
kevin 91
kevin 91
首先需要使用 name 和 id 列進行分組並獲取每個組合的計數。
預期 Output:
name id count
kevin 90 13
91 2
elly 91 15
john 90 6
adam 90 3
91 20
anjelo 90 12
91 19
然后需要使用以下條件對違規進行分類。
一個名字只包含一個 id (90 或 91),它不是違規(例如 elly 和 john不是違規者)。
名稱包含兩個 id ,
i.) 90 :小於 5 和91 :任意數(大於 0)>>>>>>>不是違規者(例如:adam)
ii.) 所有其他 id 組合>>>>>違規者(例如:kevin 和 anjelo)
最后期待Dataframe:
name violation
kevin 1
elly 0
john 0
adam 0
anjelo 1
我這樣做的目的是:
首先,我使用名稱和 ID 分組並獲取每個組合的計數(但此方法不返回上面顯示的 dataframe。)
df.groupby(['name', 'id']).size().reset_index(name='counts')
在第二部分中,我只知道如果 name 包含兩個 ids(90 和 91),如何識別違規者。 我不知道如何將上述條件給予已確定的違規者。
x = df.groupby('name').id.unique().reset_index()
x['Violation'] = x.id.apply(lambda x: 1 if (90, 91) in zip(x, x[1:]) else 0)
x.drop('id', 1, inplace=True)
x
真的很感謝你的支持!!!!!!!!!!!!!!!
讓我們嘗試使用crosstab
和 boolean 掩碼來定位違規者:
# frequency table
s = pd.crosstab(df['name'], df['id'])
m1 = s.ne(0).sum(1).eq(1) # condition 1
m2 = ~m1 & s[90].lt(5) & s[91].gt(0) # condition 2
out = (~m1 & ~m2).view('i1').to_frame('violator') # violators
細節:
使用crosstab
計算頻率表:
print(s)
90 91
adam 3 20
anjelo 12 19
elly 0 15
john 6 0
kevin 13 2
創建 boolean 掩碼,表示名稱僅包含一個 id(90 或 91) 的條件:
print(m1)
name
adam False
anjelo False
elly True # -> Non violator
john True # -> Non violator
kevin False
dtype: bool
創建 boolean 掩碼表示名稱包含兩個 id 的條件,並且 90 的值小於 5 而 91 的值大於 0 :
print(m2)
name
adam True # -> Non violator
anjelo False
elly False
john False
kevin False
dtype: bool
結合condition 1
和condition 2
得到違規者:
print(out)
violator
name
adam 0
anjelo 1
elly 0
john 0
kevin 1
您還可以在分組步驟之后嘗試 pivot 和 dataframe:
import pandas as pd
pv=pd.pivot_table(df, values = 'counts', index=['name'], columns = 'id').reset_index().fillna(0)
pv.columns = pv.columns.map(str)
之后,您可以應用邏輯以獲得您的違規標志:
import numpy as np
pv['violation'] = np.where((pv['90']==0) | (pv['91']==0) | (pv['90']<5) & (pv['91']>0),0,1)
獲得 groupby 計數后,為什么不過濾掉 ID=90 且 count<5 的行並繼續執行您的邏輯? 您可以在刪除之前獲取一組名稱,並將其與最終的 output 合並,最后將違規中的 nas 填寫為 0。
import numpy as np
g=df.groupby(['name','id']).size().to_frame('count').reset_index()#Groupby to get dataframe with count
#Allocate viloation
g['violation']=np.where((~g.name.duplicated(keep=False))|(g.id.eq(90)&g['count'].le(5)|g.id.eq(91)&g['count'].gt(0)),0,1)
print(g)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.