Pandas 通过特定行之间的掩蔽来子集df

Pandas 通过特定行之间的掩蔽来子集df,pandas,dataframe,subset,mask,Pandas,Dataframe,Subset,Mask,我正试图通过删除位于特定值之间的行来子集pandasdf。问题是这些值可能位于不同的行,因此我无法选择固定行 具体来说,我想删除介于ABC xxx和整数5之间的行。这些值可能位于df中的任何位置,并且长度不相等 注意:字符串ABC后面将跟随不同的值 我考虑返回包含这两个值的所有索引 但若我能返回这两个值之间的所有行,那个么掩码的工作效果会更好吗 df = pd.DataFrame({ 'Val' : ['None','ABC','None',1,2,3,4,5,'X',1,2,'ABC'

我正试图通过删除位于特定值之间的行来子集pandas
df
。问题是这些值可能位于不同的行,因此我无法选择固定行

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

注意:字符串
ABC
后面将跟随不同的值

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

但若我能返回这两个值之间的所有行,那个么掩码的工作效果会更好吗

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

如果
ABC
总是在
5
之前,并且总是成对(
ABC
5
)获取具有
np的值的索引。其中
zip
,并通过
~/code>使用反转掩码获取-last filter by
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
输出

    Val
0   None
8   X
9   1
10  2
如果有多个“ABC”和5个,则您可以选择以下版本。 这样,您就可以得到除第一个
ABC
和最后一个
5

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]

99%的时候总会有一个。但有时会有两个。不超过2个though@JPA0888-答案已编辑,您能否使用真实数据进行检查?如果不工作,使用真实数据返回什么
print(m1)
print(m2)
?我需要它来处理这些值之间的一个或两个索引。@JPA0888-是的,返回什么
print(m1)
print(m2)
?如果我删除连接,效果会很好。谢谢@jezraelw
X
1
2
是从哪里来的?我不明白你的问题如果有2个ABC和2个5,那么这将给出第一个ABC和最后5个ABC之间的值。是的,抱歉,我将重新解释这个问题。它不在第一个ABC和最后5个ABC之间。它位于这些值的集合之间。所以ABC和5可能在第2行和第10行。另一对值可能位于第20行和第25行。所以我需要删除2-10和20-25之间的行。这有意义吗?@JPA0888-检查我的答案以获得解决方案。
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]