通过在特定行之间进行屏蔽来子集 df
subset df by masking between specific rows
我正在尝试通过删除介于特定值之间的行来对 pandas df
进行子集化。问题是这些值可以在不同的行,所以我不能 select 固定行。
具体来说,我想删除介于 ABC xxx
和整数 5
之间的行。这些值可以落在 df
中的任何位置并且长度不等。
注意:字符串ABC
后面会跟不同的值。
我考虑过 returning 所有包含这两个值的索引。
但是如果我可以 return 所有行 在 这两个值之间,掩码会更好吗?
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.where
, zip
并获取索引值 - 最后一个过滤器 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
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'和5个,那么你就是下面的版本。
有了这个,你得到的 df 除了第一个 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]
我正在尝试通过删除介于特定值之间的行来对 pandas df
进行子集化。问题是这些值可以在不同的行,所以我不能 select 固定行。
具体来说,我想删除介于 ABC xxx
和整数 5
之间的行。这些值可以落在 df
中的任何位置并且长度不等。
注意:字符串ABC
后面会跟不同的值。
我考虑过 returning 所有包含这两个值的索引。
但是如果我可以 return 所有行 在 这两个值之间,掩码会更好吗?
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.where
, zip
并获取索引值 - 最后一个过滤器 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
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'和5个,那么你就是下面的版本。
有了这个,你得到的 df 除了第一个 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]