我试图让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
的所有行。怎么样?
理想情况下,如果有多个匹配项,则要保留的第一行是第一次匹配的位置。
答案 0 :(得分:3)
如果您只想从第一个匹配开始选择,您可以相应地选择第一个匹配的index
和slice
- 如果{{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
这是有效的,因为cumsum
将True
视为等于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
这是因为flatnonzero
将False
视为等于零,将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]