Python 为每组保留最高的单个匹配项

Python 为每组保留最高的单个匹配项,python,pandas,max,pandas-groupby,Python,Pandas,Max,Pandas Groupby,我正在努力使用pandas根据2个groupby条件进行过滤 假设我有以下数据: 每一行表示分别来自2个数据源(src1,src2)的事物比较(id1,id2) 分数表示事物之间的相似程度(越高越好) 我试图做的是groupby src1+id1+src2,只保留得分最高且count=1的行 这是我的代码: df = pd.DataFrame(data) df['count'] = 1 groups = df.groupby(['src1', 'id1', 'src2', 'score'])

我正在努力使用
pandas
根据2个
groupby
条件进行过滤

假设我有以下数据:

  • 每一行表示分别来自2个数据源(
    src1
    src2
    )的事物比较(
    id1
    id2
  • 分数表示事物之间的相似程度(越高越好)
我试图做的是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
我遇到的问题是:

  • 不使用reset_index()
    :如果我不使用
    reset_index()
    ,每当我尝试访问分数计数进行筛选时,我会得到一个键错误
  • reset_index()
    :如果我使用它,那么我“丢失”了我的groupby(即每一行变成一个新的单独行,而我的筛选结果只产生一行)
我如何扩展下面的表达式,以便对于
每组
I
仅保留
组中
最大分数
计数=1的行?

groups = df.groupby(['src1', 'id1', 'src2', 'score']).agg(
    {'id2': 'unique', 'count': 'sum'})
用于在没有新帮助器列的情况下获取计数,然后通过不同的分组列获得类似的get
max
值,通过
按位和
的链接条件进行比较和筛选:

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
m1=df.groupby(['src1','id1','src2','score'])['id1'].transform('size')

#您的代码
df=pd.DataFrame(数据)
df['count']=1
groups=df.groupby(['src1','id1','src2','score']).agg(
{'id2':'unique','count':'sum'})
#那就做吧
groups=groups.sort_值(按=['src1','id1','src2','score'],升序=False)
groups=groups.groupby(['src1','id1','src2',])。head(1)[groups['count']==1]
id2计数
src1 id1 src2分数
A 222 B 9[222]1
111 B 10[111]1

它确实可以工作,但会抛出一个
UserWarning:Boolean系列键将被重新索引以匹配数据帧索引。
警告上一个groupby(Python=3.5.2,Pandas=0.23.0)如果您担心它,那么
groups=groups.sort_值(按=['src1','id1','src2','score'],升序=False)groups=groups.groupby(['src1','id1','src2',])。head(1)groups=groups[groups['count']==1]
因为解决方案的第一部分比第二部分更干净(根据我的代码改编),我想知道:它是否也同样有效?似乎您要计算两次
groupby
,而我是在一个500MB的数据集上这样做的,所以我担心performance@PandaCoder-嗯,这是一个很难回答的问题,是真实数据中最好的测试。因为分组列不同,所以有两个groupby。第一个方法中没有输入错误吗?应该是
['id2'].transform('size')
而不是
['id1'].transform('size')
?FYI在250MB数据集上进行了测试,第1种方法似乎要快得多(0.9秒vs 2.6秒)。原因可能是它没有计算
id2
的列表(
agg({'id2':'unique'
),并且没有添加
计数列(仅保留相关行)。第1种方法的其他好处:当我将其应用于具有其他列的数据框时,结果是一个包含所有列的数据框,而使用第2种方法时,我只获取groupby列。@PandaCoder-实际上是一样的,需要从数据框中选择一列,而不需要选择使用哪一列。原因是
transform
需要一列,但
size
从索引中计数,而不是按此列。此列仅用于与其他函数兼容。但如果使用
transform
+
max
,则此处是在
transform
之前指定的最大自列数
reset = groups.reset_index()
reset[reset['score'] == reset['score'].max()]

  src1  id1 src2  score  count    id2
1    A  111    B     10      1  [111]
groups = df.groupby(['src1', 'id1', 'src2', 'score']).agg(
    {'id2': 'unique', 'count': 'sum'})
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
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