Python 文本处理(str.contains)

Posted

技术标签:

【中文标题】Python 文本处理(str.contains)【英文标题】:Python Text processing (str.contains) 【发布时间】:2018-06-10 15:50:10 【问题描述】:

我在 Pandas 中使用 str.contains 进行文本分析。如果对于“我的最新数据工作是一名分析师”这句话,我想要“数据”和“分析师”这两个词的组合,但同时我想指定用于组合的两个词之间的词数(这里是“数据”和“分析师”之间的 2 个单词。目前我正在使用 (DataFile.XXX.str.contains('job') & DataFile.XXX.str.contains('Analyst') 来获取“工作分析师”。 如何指定 str.contains 语法中两个单词之间的单词数。 提前致谢

【问题讨论】:

能否分享您的 DataFrame 示例。 Pandas 可以是非常有用的库,但它并不适用于所有内容。文本分析......也许......取决于......很可能不是。请在提出更多问题之前花 30 分钟阅读以下内容:How to Ask。 欢迎来到 SO。不幸的是,这不是一个讨论论坛或教程服务。请花时间阅读How to Ask 和该页面上的其他链接。 我知道如何回答这个问题。但我不会,因为你的问题不符合本站的标准。请提供minimal reproducible example 并阅读How to Ask.. 【参考方案1】:

你不能。至少,不是以简单或标准化的方式。

即使是基础知识,例如您如何定义“单词”,也比您想象的要复杂得多。很多。单词解析和词汇接近度(例如“两个单词在句子 s 中的距离 D 内吗?”)都是 natural language processing (NLP) 的领域。 NLP 和邻近搜索不是基本 Pandas 的一部分,也不是 Python 标准字符串处理的一部分。您可以导入 NLTK, the Natural Language Toolkit 之类的东西以一般方式解决此问题,但那完全是另一回事了。

让我们看一个简单的方法。首先,您需要一种将字符串解析为单词的方法。按照 NLP 标准,以下是粗略的,但适用于更简单的情况:

def parse_words(s):
    """
    Simple parser to grab English words from string.
    CAUTION: A simplistic solution to a hard problem. 
             Many possibly-important edge- and corner-cases 
             not handled. Just one example: Hyphenated words.
    """
    return re.findall(r"\w+(?:'[st])?", s, re.I)

例如:

>>> parse_words("and don't think this day's last moment won't come ")
['and', "don't", 'think', 'this', "day's", 'last', 'moment', "won't", 'come']

那么您需要一种方法来查找列表中找到目标词的所有索引:

def list_indices(target, seq):
    """
    Return all indices in seq at which the target is found.
    """
    indices = []
    cursor = 0
    while True:
        try:
            index = seq.index(target, cursor)
        except ValueError:
            return indices
        else:
            indices.append(index)
            cursor = index + 1

最后是一个决策包装器:

def words_within(target_words, s, max_distance, case_insensitive=True):
    """
    Determine if the two target words are within max_distance positiones of one
    another in the string s.
    """
    if len(target_words) != 2:
        raise ValueError('must provide 2 target words')

    # fold case for case insensitivity
    if case_insensitive:
        s = s.casefold()
        target_words = [tw.casefold() for tw in target_words]
        # for Python 2, replace `casefold` with `lower`

    # parse words and establish their logical positions in the string
    words = parse_words(s)
    target_indices = [list_indices(t, words) for t in target_words]

    # words not present
    if not target_indices[0] or not target_indices[1]:
        return False

    # compute all combinations of distance for the two words
    # (there may be more than one occurance of a word in s)
    actual_distances = [i2 - i1 for i2 in target_indices[1] for i1 in target_indices[0]]

    # answer whether the minimum observed distance is <= our specified threshold
    return min(actual_distances) <= max_distance

那么:

>>> s = "and don't think this day's last moment won't come at last"
>>> words_within(["THIS", 'last'], s, 2)
True

>>> words_within(["think", 'moment'], s, 2)
False

剩下要做的就是将其映射回 Pandas:

df = pd.DataFrame('desc': [
    'My latest Data job was an Analyst',
    'some day my prince will come',
    'Oh, somewhere over the rainbow bluebirds fly',
    "Won't you share a common disaster?",
    'job! rainbow! analyst.'
])

df['ja2'] = df.desc.apply(lambda x: words_within(["job", 'analyst'], x, 2))
df['ja3'] = df.desc.apply(lambda x: words_within(["job", 'analyst'], x, 3))

这基本上就是您解决问题的方法。请记住,这是一个粗略而简单的解决方案。一些简单提出的问题不是简单回答的。 NLP 问题经常在其中。

【讨论】:

以上是关于Python 文本处理(str.contains)的主要内容,如果未能解决你的问题,请参考以下文章

Python Pandas str.contains() 行中带有超链接

python pandas.Series.str.contains Whole WORD

Python series.str.contains 框架中正则表达式中的变量

Python pandas,使用 .str.contains 搜索数据框列的子字符串时出错

在“string”中的 .str.contains 和“string”之间分析哪个更快

使用带有 python/pandas 的 dict 理解与 str.contains 进行部分字符串匹配