更简单的 python 等价于 R 风格的 grep,包括多个要匹配的东西

Posted

技术标签:

【中文标题】更简单的 python 等价于 R 风格的 grep,包括多个要匹配的东西【英文标题】:simpler python equivalent of R-style grep, including multiple things to match 【发布时间】:2019-07-09 00:01:06 【问题描述】:

这个问题几乎与this one 重复,但有一些调整。

获取以下数据框,并获取其中包含“sch”或“oa”的列的位置。在 R 中足够简单:

df <- data.frame(cheese = rnorm(10),
                 goats = rnorm(10), 
                 boats = rnorm(10), 
                 schmoats = rnorm(10), 
                 schlomo = rnorm(10),
                 cows = rnorm(10))

grep("oa|sch", colnames(df))

[1] 2 3 4 5

write.csv(df, file = "df.csv")

现在在 python 中,我可以使用一些详细的列表理解:

import pandas as pd
df = pd.read_csv("df.csv", index_col = 0)
matches = [i for i in range(len(df.columns)) if "oa" in df.columns[i] or "sch" in df.columns[i]]

matches
Out[10]: [1, 2, 3, 4]

我想知道是否有 在 python 中比上面的列表理解示例更好的方法。具体来说,如果我有几十个字符串要匹配怎么办。在 R 中,我可以做类似

regex <- paste(vector_of_strings, sep = "|")
grep(regex, colnames(df))

但是如何在 python 中使用列表理解 来做到这一点并不明显。也许我可以使用字符串操作以编程方式创建将在列表内执行的字符串,以处理所有重复的 or 语句?

【问题讨论】:

谢谢,但我正在寻找 python 解决方案。我知道如何在 R 中做到这一点。将澄清。 【参考方案1】:

也许您正在寻找re 模块?

import re
pattern = re.compile("oa|sch")
[i for i in range(len(df.columns)) if pattern.search(df.columns[i])]
# [1, 2, 3, 4]

与 R 的向量化相比,可能不是最好的,但列表理解应该没问题。

如果你想将字符串连接在一起,你可以这样做

"|".join(("oa", "sch"))
# 'oa|sch'

【讨论】:

这看起来不错,但不太好用。我得到TypeError: expected string or bytes-like object,然后当我将i 设置为零并执行pattern.search(dmat.columns[i]) 时,我得到以下不是布尔值的输出:&lt;_sre.SRE_Match object; span=(0, 3), match='L1_'&gt;。可能一些挖掘可能会出现如何让re 给我一个布尔值,但无论如何请告诉我你是否知道! [i for i in range(len(df.columns)) if pattern.search(df.columns[i]) is not None] 有帮助吗?我得到了类似的输出,但我认为只有返回某些东西才重要。 不,很遗憾没有。 奇怪的是,if not None 东西在列表理解之外起作用,但在它内部不起作用。 通过将df.columns[i] 包裹在str() 中解决了这个问题:***.com/questions/43727583/…【参考方案2】:

使用 pandas 的 DataFrame.filter 运行相同的正则表达式:

df.filter(regex = "oa|sch").columns
# Index(['goats', 'boats', 'schmoats', 'schlomo'], dtype='object')

df.filter(regex = "oa|sch").columns.values
# ['goats' 'boats' 'schmoats' 'schlomo']

数据

import numpy as np
import pandas as pd

np.random.seed(21419)

df = pd.DataFrame('cheese': np.random.randn(10),
                   'goats': np.random.randn(10), 
                   'boats': np.random.randn(10), 
                   'schmoats': np.random.randn(10), 
                   'schlomo': np.random.randn(10),
                   'cows': np.random.randn(10))

对于多个要搜索的字符串:

rgx = "|".join(list_of_strings)

df.filter(regex = rgx)

要返回索引,请考虑来自@Divakar 的向量化 numpy 解决方案。请注意,与 R 不同,Python 是零索引的。

def column_index(df, query_cols):
    cols = df.columns.values
    sidx = np.argsort(cols)
    return sidx[np.searchsorted(cols,query_cols,sorter=sidx)]

column_index(df, df.filter(regex="oa|sch").columns)
# [1 2 3 4] 

【讨论】:

这行得通,但我真的想要索引。主要是因为 numpy 没有列名,我需要求助于我从中构建矩阵的数据框。我想从过滤后的数据框中获取索引是微不足道的。但是我需要做一个 df 操作来获取我在其他地方使用的索引。我想在这个问题中我应该只使用一个字符串数组。 @generic_user 一个 numpy 字符串数组几乎不是你想要的 那么,跟踪 numpy 矩阵所代表的内容的好做法是什么?来自 R,我觉得我在蒙着眼睛编码。 @juanpa.arrivillaga 查看从这篇文章返回搜索字符串的列索引的编辑,有趣的是,那里的 OP 询问了 Python 中的 R 等效项:Get column index from column name in python pandas。最后,您的问题正在变成XY Problem。告诉我们真正的、完整的 X 问题,而不是您提出的 Y 解决方案。 如果您正在使用字符串,您可能只想坚持使用 vanilla python。 Pandas 确实提供了一些方便的字符串实用程序,但它也不是专门用于字符串的

以上是关于更简单的 python 等价于 R 风格的 grep,包括多个要匹配的东西的主要内容,如果未能解决你的问题,请参考以下文章

Pandas 等价于 R 的 which()

R 是不是有与 Python 中的 reduce() 等价的东西?

Python 等价于 Java StringBuffer?

等价于 python 的 auto.arima()

R 在 Python 中的 browser() 等价物

Python 中的 rpart.plot 等价于啥?我想可视化我的随机森林的结果