【问题标题】:subset df by masking between specific rows通过屏蔽特定行之间的子集 df
【发布时间】:2020-01-12 21:37:31
【问题描述】:

我正在尝试通过删除介于特定值之间的行来对 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

【问题讨论】:

  • X12 是从哪里来的?

标签: pandas dataframe subset mask


【解决方案1】:

如果 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

【讨论】:

  • 99% 的时间里总会有一个。但有时会有 2 个。不过不会超过 2 个
  • @JPA0888 - 答案已编辑,您可以检查真实数据吗?如果不工作,什么返回 print (m1)print (m2) 与真实数据?
  • 我需要它来处理这些值之间的一两个索引。
  • @JPA0888 - 是的,print (m1)print (m2) 返回什么?
  • 如果我删除连接它会很好。谢谢@jezrael
【解决方案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 个,那么你是下面的版本。 有了这个,你得到除了第一个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]

【讨论】:

  • 我不明白你的问题
  • 如果有 2 个 ABC 和 2 个 5,那么这将给出第一个 ABC 和最后 5 个之间的值。
  • 是的,抱歉,我会重新提出这个问题。它不在第一个 ABC 和最后 5 个之间。它在这些值的集合之间。所以 ABC 和 5 可能在第 2 行和第 10 行。另一对这些值可能在第 20 和 25 行。所以我需要删除 2-10 和 20-25 之间的行。这有意义吗?
  • @JPA0888 - 检查我的答案以获得解决方案。
猜你喜欢
  • 1970-01-01
  • 2013-08-20
  • 1970-01-01
  • 2012-07-29
  • 2021-12-13
  • 1970-01-01
  • 2012-02-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多