如何解决带条件的groupby并对python进行分类
我有 2 列(名称和 ID)的数据框。有成千上万的名字。但是每个名字,只有两个id(90和91,所以id列中只包含90和91)。
示例数据框如下所示。
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 列groupby并获取每个组合的计数。
预期输出:
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)>>>>>>> 不是违规者强>(例如:亚当)
ii.) 所有其他 id 组合>>>>> 违规者(例如:kevin 和 anjelo)
最终预期的数据帧:
name violation
kevin 1
elly 0
john 0
adam 0
anjelo 1
我尝试这样做的目的:
首先,我使用 name 和 id 分组并获取每个组合的计数(但此方法不返回上述数据帧。)
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
和布尔掩码来定位违规者:
# 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
创建表示条件的布尔掩码,其中一个名称只包含一个 id(90 或 91):
print(m1)
name
adam False
anjelo False
elly True # -> Non violator
john True # -> Non violator
kevin False
dtype: bool
创建表示条件的布尔掩码,其中 一个名称包含两个 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
,
您也可以尝试在分组步骤后旋转数据框:
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),1)
,
获得 groupby 计数后,为什么不过滤掉 ID=90 和 count
,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)),1)
print(g)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。