如何通过施加在两列上的多个条件来删除Pandas数据框中的行?

时间:2018-08-22 02:29:21

标签: python pandas

这是一个捕捉我的问题的玩具示例。有什么帮助吗?谢谢!

d = {'a': [1,1,1,2,2,2,3,3,3],
     'b': [1,2,3,1,2,3,1,2,3]}

df = pd.DataFrame(d)

针对此结果:

我想删除(a,b)=(1,3)或(2,1)的两行。

result = pd.DataFrame({'a': [1,1,2,2,3,3,3],
                       'b': [1,2,2,3,1,2,3]})

实际上,我会有一个排除列表,该列表会随时间更新: 排除= [[1,3],[2,1],[3,4],........]

5 个答案:

答案 0 :(得分:3)

当我们应该能够挥动双手时,这就像发射一门大炮,但是:

df = pd.DataFrame({'a': [1,1,1,1,2,2,2,3,3,3],
                   'b': [1,1,2,3,1,2,3,1,2,3]})

excl = [[1, 3], [2, 1]]
keep = df.merge(pd.DataFrame(excl, columns=['a','b']),
                how='left', indicator=True)._merge == 'left_only'

给我

In [91]: df.loc[keep]
Out[91]: 
   a  b
0  1  1
1  1  1
2  1  2
5  2  2
6  2  3
7  3  1
8  3  2
9  3  3

(请注意,出于理智目的,我添加了重复的1,1行。)

疯狂的方法2 :(有效地)使用分类编码:

codes = pd.concat([df, edf], sort=False).groupby(["a","b"]).ngroup()
keep = ~codes.iloc[:len(df)].isin(codes.iloc[len(df):])
df = df.loc[keep]

答案 1 :(得分:2)

将“禁止”行的列表转换为列名称与原始数据框不同的数据框:

to_drop = pd.DataFrame(excl, columns=('c','d')) # Different column names!

合并两个数据框。将有NaN个不匹配的地方:

combined = df.merge(to_drop, how='outer', left_on=['a','b'], right_on=['c','d'])

最初从第二个数据帧中取出任何列,找出NaN在哪里,并使用它们的索引从第一个数据帧中提取有效行:

df[combined.isnull()['d']]
#   a  b
#0  1  1
#1  1  2
#4  2  2
#5  2  3
#6  3  1
#7  3  2
#8  3  3

您可能会看到警告:

  

UserWarning:布尔系列键将被重新索引以匹配DataFrame索引。

您现在可以忽略它。

答案 2 :(得分:2)

另一种棘手的解决方案:

df = pd.DataFrame({'a': [1,1,1,2,2,2,3,3,3],
                   'b': [1,2,3,1,2,3,1,2,3]})
to_drop = pd.DataFrame({'a': [1, 2], 'b': [3, 1]})
result = df.merge(to_drop, on=['a', 'b'], how='outer', indicator=True) 
result = result[result['_merge'] == 'left_only'].drop('_merge', axis=1)

结果:

   a  b
0  1  1
1  1  2
4  2  2
5  2  3
6  3  1
7  3  2
8  3  3

答案 3 :(得分:2)

tupleisin一起使用

df[~df.apply(tuple,1).isin([(1,3),(2,1)])]
Out[568]: 
   a  b
0  1  1
1  1  2
4  2  2
5  2  3
6  3  1
7  3  2
8  3  3

答案 4 :(得分:-1)

尝试:

result = df.loc[(df['a'] == 1 & df['b'] == 3) | (df['a'] == 2 & df['b'] == 1)]