在所有Pandas DataFrame列中搜索字符串并过滤

hor*_*01d 30 python pandas

认为这将是直接的,但在追踪优雅的方式来同时搜索数据框中的所有列以进行部分字符串匹配时遇到了一些麻烦.基本上我将如何同时应用于df['col1'].str.contains('^')整个数据框并过滤到包含匹配记录的任何行?

unu*_*tbu 32

Series.str.contains方法需要一个正则表达式模式(默认情况下),而不是文字字符串.因此str.contains("^")匹配任何字符串的开头.由于每个字符串都有一个开头,所以一切都匹 而是str.contains("\^")用来匹配文字^字符.

要检查每一列,您可以使用for col in df迭代列名称,然后调用str.contains每列:

mask = np.column_stack([df[col].str.contains(r"\^", na=False) for col in df])
df.loc[mask.any(axis=1)]
Run Code Online (Sandbox Code Playgroud)

或者,您可以传递regex=Falsestr.contains测试使用Python in运算符; 但(一般情况下)使用正则表达式更快.

  • 如果您的 df 具有不同 dtypes 的列,您需要强制转换 `df[col].astype('str')` 才能正常工作。 (4认同)
  • @unutbu你怎么看待'mask = df.apply(lambda x:x.str.contains(r'​​\ ^',na = False))`而不是`np.column_stack`? (3认同)
  • 嘿@unutbu,向您提问。当可以使用`pd.DataFrame(...)。transpose()`时,为什么还要使用`np.column_stack'? (2认同)
  • 当“ mask”是布尔型NumPy数组时,“ df.loc [mask]”会选择“ mask”为True的行。但是,如果mask是一个DataFrame,则df.loc [mask]从df中选择其* index *值与对应于True值的mask中的索引值匹配的行。索引的这种对齐方式在您需要时会很棒,但在不需要时会降低性能。简而言之,如果不需要索引,请使用NumPy数组而不是DataFrame。同样,创建DataFrame比创建NumPy数组要慢得多,因此在这里使用`pd.DataFrame([...])。T`没有优势。 (2认同)
  • @零:也很好。从好的方面来说,它的编写要短一些。在不利的一面,它返回一个DataFrame而不是NumPy数组。由于我们使用“掩码”来建立索引,因此只有数组值才重要,而没有任何辅助标签。为了确保Pandas不会进行任何不需要的索引对齐,我倾向于使用布尔NumPy数组而不是Series进行布尔索引(尽管实际上,Pandas做对了,所以没关系)。最后,我认为您所使用的归结为个人品味。 (2认同)

Pun*_*nha 18

试试:

df.apply(lambda row: row.astype(str).str.contains('TEST').any(), axis=1)
Run Code Online (Sandbox Code Playgroud)

  • 要使搜索与大小写无关: df.apply(lambda row: row.astype(str).str.contains('TEST'.lower(), case=False).any(), axis=1) (3认同)
  • 与最佳答案相比非常慢:/sf/answers/1864875981/ (2认同)

rac*_*hwa 9

或者,您可以使用eqany

df[df.eq('^').any(axis=1)]
Run Code Online (Sandbox Code Playgroud)


tho*_*olf 5

这是一个解决在数据框的所有列中进行文本搜索的问题的函数df

def search(regex: str, df, case=False):
    """Search all the text columns of `df`, return rows with any matches."""
    textlikes = df.select_dtypes(include=[object, "string"])
    return df[
        textlikes.apply(
            lambda column: column.str.contains(regex, regex=True, case=case, na=False)
        ).any(axis=1)
    ]
Run Code Online (Sandbox Code Playgroud)

它与现有答案的不同之处在于,它既保留在 pandas API 中,又承认 pandas 在列处理方面比行处理更有效。此外,这被打包为一个纯函数:-)

相关文档: