我正在努力使用pandas
来基于2个groupby
条件进行过滤
假设我有以下数据:
id1
,id2
)的事物(src1
,src2
)的比较data = [
{'src1': 'A', 'id1': '111', 'src2': 'B', 'id2': '111', 'score': 10},
{'src1': 'A', 'id1': '222', 'src2': 'B', 'id2': '222', 'score': 9},
{'src1': 'A', 'id1': '111', 'src2': 'B', 'id2': '222', 'score': 2},
{'src1': 'A', 'id1': '222', 'src2': 'B', 'id2': '111', 'score': 4},
{'src1': 'A', 'id1': 'default', 'src2': 'B', 'id2': '111', 'score': 3},
{'src1': 'A', 'id1': 'default', 'src2': 'B', 'id2': '222', 'score': 3},
]
我想做的是 groupby src1 + id1 + src2并仅保留得分最高且count = 1的行
这是我的代码:
df = pd.DataFrame(data)
df['count'] = 1
groups = df.groupby(['src1', 'id1', 'src2', 'score']).agg(
{'id2': 'unique', 'count': 'sum'})
print(groups)
我得到以下信息:
id2 count
src1 id1 src2 score
A 111 B 2 [222] 1 # DISCARD because below has higher score (10>2)
10 [111] 1 # KEEP
222 B 4 [111] 1 # DISCARD because below has higher score (9>4)
9 [222] 1 # KEEP
default B 3 [111, 222] 2 # DISCARD because count=2
我遇到的问题:
WITHOUT reset_index()
:如果我不使用reset_index()
,每当我尝试访问得分或 count 进行过滤时,都会得到一个 KeyError groups = df.groupby(['src1', 'id1', 'src2', 'score']).agg(
{'id2': 'unique', 'count': 'sum'})
groups[groups['score'] == groups['score'].max()]
KeyError: 'score'
reset_index()
:如果我使用它,则会“丢失”我的分组依据(即,每行变成一个新的单独行,而我的过滤结果仅产生1行reset = groups.reset_index()
reset[reset['score'] == reset['score'].max()]
src1 id1 src2 score count id2
1 A 111 B 10 1 [111]
如何扩展表达式以下内容,以便EACH GROUP
和ONLY KEEP
和MAX score
count=1
将行分组?
groups = df.groupby(['src1', 'id1', 'src2', 'score']).agg(
{'id2': 'unique', 'count': 'sum'})
答案 0 :(得分:2)
使用GroupBy.transform
来获得计数,而无需使用GroupBy.size
来创建新的帮助程序列,然后通过不同的分组列来获得相似的max
值,使用boolean indexing
进行比较并通过链接条件进行过滤&
的{{1}}:
bitwise AND
您的解决方案应更改:
m1 = df.groupby(['src1', 'id1', 'src2', 'score'])['id1'].transform('size') <= 1
m2 = df.groupby(['src1', 'id1', 'src2'])['score'].transform('max') == df['score']
df = df[m1 & m2]
print (df)
id1 id2 score src1 src2
0 111 111 10 A B
1 222 222 9 A B
答案 1 :(得分:1)
其中一种方法
df['count'] = 1
groups = df.groupby(['src1', 'id1', 'src2', 'score']).agg(
{'id2': 'unique', 'count': 'sum'})
m1 = groups['count'] <= 1
df = groups.reset_index(level=3)
m2 = (df.groupby(level=[0,1,2])['score'].transform('max') == df['score']).values
groups = groups[m1 & m2]
print (groups)
id2 count
src1 id1 src2 score
A 111 B 10 [111] 1
222 B 9 [222] 1