Python 如果列中的值不符合另一列中的要求,则删除行

Python 如果列中的值不符合另一列中的要求,则删除行,python,pandas,Python,Pandas,假设我有这个数据帧: df = DataFrame({'ID': [1001,4003,1001, 4003, 7000, 7000], 'col_2': ['3', '8', '2', '1','7','9'], 'col_3': ['Steak','Chicken','Chicken','Steak','Chicken','Chicken']}) 我想创建3个数据帧。 前两个是每个有鸡的ID的数据帧。第二个是所有有牛肉的身份证。这很容易:

假设我有这个数据帧:

df = DataFrame({'ID': [1001,4003,1001, 4003, 7000, 7000], 
            'col_2': ['3', '8', '2', '1','7','9'], 
            'col_3': ['Steak','Chicken','Chicken','Steak','Chicken','Chicken']})
我想创建3个数据帧。 前两个是每个有鸡的ID的数据帧。第二个是所有有牛肉的身份证。这很容易:

dfsteak = df[~(df['col_3'] != 'Steak')]
dfchicken =  df[~(df['col_3'] != 'Chicken')]

但是对于第三个问题,如果一个身份证一次没有鸡肉,另一次没有牛排,我想取消任何一行。在这个例子中,这将是ID7000,他只点了鸡肉。但是我该如何实现呢?

使用
filter
any

df.groupby('ID').filter(lambda x : ((x['col_3']=='Steak').any())&((x['col_3']=='Chicken').any()))
Out[14]: 
     ID col_2    col_3
0  1001     3    Steak
1  4003     8  Chicken
2  1001     2  Chicken
3  4003     1    Steak
过滤掉ID7000

df.groupby('ID').filter(lambda x : ~((x['col_3']=='Steak').any())&((x['col_3']=='Chicken').any()))
Out[16]: 
     ID col_2    col_3
4  7000     7  Chicken
5  7000     9  Chicken

这里有一个直观的方法。其思想是创建一个系列,通过
ID
col\u 3
聚合为
set

然后,当映射的
不是
{'Steak','Chicken'}
的超集时,进行筛选

s = df.groupby('ID')['col_3'].apply(set)
df = df[~(df['ID'].map(s) >= {'Steak', 'Chicken'})]

print(df)

     ID col_2    col_3
4  7000     7  Chicken
5  7000     9  Chicken

非常有趣的解决方案。它也比
filter()
快,有点令人惊讶。@lilicent,是的,
filter
的问题是当它与低效的
lambda
函数一起使用时。使用一次性构建成本完成
s
时不需要的多次遍历速度提高25%:
f=lambda x:((x='Steak').any())和((x='Chicken').any())df.groupby('ID')['col_3'])filter(f)