如果字符串不等于值,则删除行 - 熊猫

时间:2021-04-14 03:50:59

标签: python pandas

如果特定值后面的字符串不等于值列表,我希望删除行。具体来说,如果 'Up' or 'Left' 之后的后续行后面没有 'Right''Down',那么我的目标是删除这些行。

import pandas as pd

df = pd.DataFrame({      
    'Label' : ['A','B','A','B','B','B','A','B','B','A','A','A'],   
    'Item' : ['X','Left','X','Left','Down','Right','Up','Y','Right','Y','Right','Up'],      
    })

df1 = df[~(df['Item'].isin(['Up','Left']).shift(1)) & (df['Item'].isin(['Right','Down']))]

   Label   Item
0      A      X
1      B   Left
2      A      X # Drop. Not Right/Down
3      B   Left
4      B   Down # Keep. Right/Down
5      B  Right
6      A     Up
7      B      Y # Drop. Not Right/Down
8      B  Right
9      A      Y
10     A  Right
11     A     Up

预期输出:

   Label   Item
0      A      X
1      B   Left
3      B   Left
4      B   Down
5      B  Right
6      A     Up
8      B  Right
9      A      Y
10     A  Right
11     A     Up

4 个答案:

答案 0 :(得分:4)

您的代码很好,只是缺少第二个条件中的 not

<块引用>

如果“Up”或“Left”之后的下一行是not,然后是 'Right' 或 'Down' 那么我的目标是删除这些行。

所以它应该是这样的:

df1 = df[~(((df['Item'].isin(['Up','Left']).shift(1)) & ~(df['Item'].isin(['Right','Down']))))]

答案 1 :(得分:2)

我修改了面具。它会立即解决您的问题 -

import pandas as pd
import numpy as np
df = pd.DataFrame({      
    'Label' : ['A','B','A','B','B','B','A','B','B','A','A','A'],   
    'Item' : ['X','Left','X','Left','Down','Right','Up','Y','Right','Y','Right','Up'],      
    })

mask = (~(df['Item'].isin(['Up','Left']) & (~df['Item'].shift(-1).isin(['Right','Down',np.NAN]))))
df1 = df[mask.shift(1,fill_value=True)]
print(df1)

输出 -

   Label   Item
0      A      X
1      B   Left
3      B   Left
4      B   Down
5      B  Right
6      A     Up
8      B  Right
9      A      Y
10     A  Right
11     A     Up

答案 2 :(得分:2)

首先创建一个 left up 掩码,用于确定 Left 列中 UpItem 值的索引。

然后移动 left up 掩码以获得 right down 掩码,确定我们要检查的位置。

lu_mask = (df['Item'] == 'Left') | (df['Item'] == 'Up')
rd_mask = lu_mask.shift(1).fillna(False)

此外,使用 right down 掩码检查该行是 Right 还是 Down

index_to_drop = ((df.loc[rd_mask, 'Item'] != 'Right') & (df.loc[rd_mask, 'Item'] != 'Down')).loc[lambda s: s == True]

最后,删除该行。

df_ = df[~df.index.isin(index_to_drop.index)]
# print(df_)

   Label   Item
0      A      X
1      B   Left
3      B   Left
4      B   Down
5      B  Right
6      A     Up
8      B  Right
9      A      Y
10     A  Right
11     A     Up

答案 3 :(得分:1)

我认为这里有更简单的解决方案,如已接受的答案:

您的解决方案通过 | 按位更改 OR 并首先移动值然后比较:

df2 = df[df['Item'].isin(['Right','Down']) | ~df['Item'].shift().isin(['Up','Left'])]
print (df2)
   Label   Item
0      A      X
1      B   Left
3      B   Left
4      B   Down
5      B  Right
6      A     Up
8      B  Right
9      A      Y
10     A  Right
11     A     Up