Python 查找包含多行匹配条件的组

Python 查找包含多行匹配条件的组,python,pandas,Python,Pandas,给定以下数据帧 df=pd.DataFrame({'A':list('aaaaaa bbbbb cccc'), “B”:列表('EFGHIJEGHJKGHJKEI')) 我想找到A中的所有元素,其中B包含“G”、“H”和“I” 因此,结果应该是 | | A | B | |---:|:----|:----| | 2 | A | G | | 3 | A | H | | 4 | A | I | | 11 | C | G | | 12 | C |

给定以下数据帧

df=pd.DataFrame({'A':list('aaaaaa bbbbb cccc'),
“B”:列表('EFGHIJEGHJKGHJKEI'))
我想找到
A
中的所有元素,其中
B
包含“G”、“H”和“I”

因此,结果应该是

|    | A   | B   |
|---:|:----|:----|
|  2 | A   | G   |
|  3 | A   | H   |
|  4 | A   | I   |
| 11 | C   | G   |
| 12 | C   | H   |
| 16 | C   | I   |
目前,我已经找到了下面的解决方案,但这似乎过于草率,我觉得我遗漏了一些明显的东西

hit=list('GHI'))
out=df[df.groupby('A')。应用(lambda x:(x['B'].isin(hit))和(x['B'].isin(hit).sum()==len(hit))。值]

让我们做
groupby
+
filter

hit = list('GHI')
out = df.groupby('A').filter(lambda x : pd.Series(hit).isin(x['B']).all())
out = out[out.B.isin(hit)]
out
Out[308]: 
    A  B
2   A  G
3   A  H
4   A  I
11  C  G
12  C  H
16  C  I

这种转换不是很明显,但我们可以通过检查每个组的大小来保持它的矢量化,与
命中相比:

d = df[df['B'].isin(hit)]
size = d.groupby('A').size()
grps = size[size.eq(len(hit))].index

d[d['A'].isin(grps)]

你有两个条件:

  • hit是组的子集:
    x['B'].isin(hit).sum()==len(hit)

  • B处的值包含在hit:
    x['B']中。isin(hit)

  • 所以你可以这样表达这两个条件

    hit = frozenset('GHI')
    print(df[df.groupby('A')['B'].transform(hit.issubset) & df['B'].isin(hit)])
    
    输出

        A  B
    2   A  G
    3   A  H
    4   A  I
    11  C  G
    12  C  H
    16  C  I
    
    表达方式:

    df.groupby('A')['B'].transform(hit.issubset)
    

    与条件1等效。

    另一种方法:首先删除那些未命中的,然后过滤所有命中的

    (df[df['B'].isin(hit)]
       .drop_duplicates(['A','B'])
       .loc[lambda x: x.groupby('A')['A'].transform('size')==len(hit)]
    )
    
    或与
    groupby()类似的想法。过滤器

    (df[df['B'].isin(hit)]
       .groupby('A')
       .filter(lambda x: x['B'].nunique()==len(hit))
    )
    
    输出:

        A  B
    2   A  G
    3   A  H
    4   A  I
    11  C  G
    12  C  H
    16  C  I
    

    下面是另一种使用布尔索引进行此操作的方法,无需使用
    groupby
    unstack
    -

    df = pd.DataFrame({'A':list('AAAAAABBBBBCCCCCC'),
                       'B':list('EFGHIJEGHJKGHJKEI')})
    
    
    filt = df['B'].isin(hit)
    
    df['C']=1
    df[filt & df['A'].isin(df[filt].set_index(['A','B']).unstack('B').dropna().index)]
    

    因为B有G和H,但不是i!我选择这个答案是因为我没有想到使用
    集合
    。这个解决方案对我来说更“易读”
        A  B
    2   A  G
    3   A  H
    4   A  I
    11  C  G
    12  C  H
    16  C  I
    
    df = pd.DataFrame({'A':list('AAAAAABBBBBCCCCCC'),
                       'B':list('EFGHIJEGHJKGHJKEI')})
    
    
    filt = df['B'].isin(hit)
    
    df['C']=1
    df[filt & df['A'].isin(df[filt].set_index(['A','B']).unstack('B').dropna().index)]
    
        A   B   C
    2   A   G   1
    3   A   H   1
    4   A   I   1
    11  C   G   1
    12  C   H   1
    16  C   I   1