簡體   English   中英

groupby 條件和分類 python

[英]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

然后需要使用以下條件對違規進行分類。

  1. 一個名字只包含一個 id (90 或 91),它不是違規(例如 elly 和 john不是違規者)。

  2. 名稱包含兩個 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 1condition 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM