过滤掉字符串匹配前的所有行

时间:2016-06-17 19:03:10

标签: python numpy pandas dataframe

我试图让DataFrame 放弃在其中一列中存在字符串匹配位置之前的所有行。

换句话说:应该保留字符串匹配的行以及后面的所有行。 (也应保留列标题。)

import pandas as pd

df = pd.read_csv(file_path)

test_string = "myUniqueMatch"    
found_match = df["Column"].str.contains(test_string).sum()

if found_match == 1:
    match_location = df[df["Column"].str.contains(test_string)].index.tolist()
    df = df.iloc[match_location]

上面我可能多余的代码会找到第一个匹配的索引位置(假设只有一个匹配)。

最后一行代码是占位符。我想在这里获得包括和跟随match_location的所有行。怎么样?

理想情况下,如果有多个匹配项,则要保留的第一行是第一次匹配的位置。

3 个答案:

答案 0 :(得分:3)

如果您只想从第一个匹配开始选择,您可以相应地选择第一个匹配的indexslice - 如果{{1},则下面不依赖于索引值是非唯一的:

index

您的代码的修复程序也只是使用slicing

df.iloc[df['strings'].tolist().index(test_string):]

上述内容很快:

df = df.iloc[match_location:]

我最初误读了 - 下面保留了行df = pd.DataFrame(np.random.choice(list('ABCDE'), 100), columns=['strings']) test_string = 'A' %timeit df.iloc[df['strings'].tolist().index(test_string):] 10000 loops, best of 3: 95 µs per loop %timeit df.iloc[np.flatnonzero(df['strings'].str.contains('A'))[0]:] 1000 loops, best of 3: 299 µs per loop %timeit df.loc[df['strings'].str.contains('A').cumsum().astype(bool)] 1000 loops, best of 3: 516 µs per loop 和紧跟下面的行,以防万一对任何人都有用:要选择匹配的所有行以及紧接着那些行的所有行,你可以使用{{ 1}}和match沿着以下几行:

.shift()

示例数据:

pd.Index.union

得到:

df.loc[df[df['strings'].str.contains(test_string)].index.union(df[df['strings'].str.contains(test_string).shift().fillna(False)].index)]

答案 1 :(得分:2)

您可以使用cumsum().astype(bool)创建布尔选择掩码:

import pandas as pd
df = pd.DataFrame({'col' : ['AA', 'AB', 'BA', 'BB', 'XX', 'AA', 'AB', 'XX', 'BA', 'BB']},
                  index=[1,2]*5)

mask = df['col'].str.contains(r'XX').cumsum().astype(bool)
print(df.loc[mask])

产量

  col
1  XX
2  AA
1  AB
2  XX
1  BA
2  BB

这是有效的,因为cumsumTrue视为等于1,将False视为等于0。

或者,您可以使用np.flatnonzero查找第一个True值的序数索引:

In [73]: df.iloc[np.flatnonzero(df['col'].str.contains(r'XX'))[0]:]
Out[73]: 
  col
1  XX
2  AA
1  AB
2  XX
1  BA
2  BB

这是因为flatnonzeroFalse视为等于零,将True视为非零值。

对于大型DataFrame,这有点快,因为它避免了累积求和 ints转换回布尔值:

In [84]: df = pd.DataFrame({'col' : ['AA', 'AB', 'BA', 'BB', 'XX', 'AA', 'AB', 'XX', 'BA', 'BB']}, index=[1,2]*5)

In [85]: df = pd.concat([df]*10000)

In [86]: %timeit df.loc[df['col'].str.contains(r'XX').cumsum().astype(bool)]
10 loops, best of 3: 46 ms per loop

In [87]: %timeit df.iloc[np.flatnonzero(df['col'].str.contains(r'XX'))[0]:]
10 loops, best of 3: 43.5 ms per loop

上述两种方法都避免依赖索引,以防索引是非唯一的。

答案 2 :(得分:1)

编辑:无视,我误读并认为你试图丢弃前面的每一行匹配。无论如何,如果这是你想要的,这是你的代码

import pandas as pd

df = pd.read_csv(file_path)
test_string = "myUniqueMatch"

mask = df["Column"].str.contains(test_string).shift(-1).fillna(False)
newDf = df.loc[~mask]