通过屏蔽特定行之间的子集df

时间:2019-09-11 05:11:20

标签: pandas dataframe subset mask

我正在尝试通过删除介于特定值之间的行来对熊猫df进行子集化。问题在于这些值可以位于不同的行,因此我无法选择固定的行。

具体地说,我想删除介于ABC xxx和整数5之间的行。这些值可以落在df中的任何位置,并且长度不相等。

注意:字符串ABC后将带有不同的值。

我考虑过返回包含这两个值的所有索引。

但是如果我可以返回这两个值之间的所有行 ,则mask可以更好地工作?

df = pd.DataFrame({
    'Val' : ['None','ABC','None',1,2,3,4,5,'X',1,2,'ABC',1,4,5,'Y',1,2],                                                   
    })

mask = (df['Val'].str.contains(r'ABC(?!$)')) & (df['Val'] == 5)   

预期输出:

     Val
0   None
8      X
9      1
10     2
15     Y
16     1
17     2

2 个答案:

答案 0 :(得分:1)

如果ABC始终在5之前并且始终对(ABC5)获取具有np.wherezip和获取介于-之间的索引值-通过isin进行最后过滤,使用~进行反转掩码:

#2 values of ABC, 5 in data
df = pd.DataFrame({
   'Val' : ['None','ABC','None',1,2,3,4,5,'None','None','None',
            'None','ABC','None',1,2,3,4,5,'None','None','None']
    })

m1 = np.where(df['Val'].str.contains(r'ABC', na=False))[0]
m2 = np.where(df['Val'] == 5)[0]

print (m1)
[ 1 12]

print (m2)
[ 7 18]

idx = [x for y, z in zip(m1, m2) for x in range(y, z + 1)]
print (df[~df.index.isin(idx)])
     Val
0   None
8      X
9      1
10     2
11  None
19     X
20     1
21     2

答案 1 :(得分:0)

a = df.index[df['Val'].str.contains('ABC')==True][0]
b = df.index[df['Val']==5][0]+1
c = np.array(range (a,b))
bad_df = df.index.isin(c)
df[~bad_df]

输出

    Val
0   None
8   X
9   1
10  2

如果“ ABC”和“ ABC”不止一个,则为以下版本。 这样,您可以获得除第一个ABC和最后一个5

以外的df
a = (df['Val'].str.contains('ABC')==True).idxmax()
b = df['Val'].where(df['Val']==5).last_valid_index()+1
c = np.array(range (a,b))
bad_df = df.index.isin(c)
df[~bad_df]