groupby 条件和分类 python
groupby with conditions and classify 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 组合>>>>> Violator(例如:kevin 和 anjelo)
最终预期的数据帧:
name violation
kevin 1
elly 0
john 0
adam 0
anjelo 1
我的尝试是为了:
首先我使用 name 和 id 进行分组并获取每个组合的计数(但此方法不 return 上面显示的数据框。)
df.groupby(['name', 'id']).size().reset_index(name='counts')
在第二部分,我只知道如果名称包含两个id(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
非常感谢您的支持!!!!!!!!!!!!!!!!
获得 groupby 计数后,为什么不过滤掉 ID=90 且计数<5 的行并继续您的逻辑?您可以在删除之前取一组名称,最后将其与您的最终输出合并,方法是将 nas 填入 violations 为 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)
让我们尝试 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
详情:
计算频率 table 使用 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),0,1)
我有包含 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 组合>>>>> Violator(例如:kevin 和 anjelo)
最终预期的数据帧:
name violation
kevin 1
elly 0
john 0
adam 0
anjelo 1
我的尝试是为了:
首先我使用 name 和 id 进行分组并获取每个组合的计数(但此方法不 return 上面显示的数据框。)
df.groupby(['name', 'id']).size().reset_index(name='counts')
在第二部分,我只知道如果名称包含两个id(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
非常感谢您的支持!!!!!!!!!!!!!!!!
获得 groupby 计数后,为什么不过滤掉 ID=90 且计数<5 的行并继续您的逻辑?您可以在删除之前取一组名称,最后将其与您的最终输出合并,方法是将 nas 填入 violations 为 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)
让我们尝试 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
详情:
计算频率 table 使用 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),0,1)