【问题标题】:How to filter strings if the first three sentences contain keywords如果前三个句子包含关键字,如何过滤字符串
【发布时间】:2020-05-20 19:27:35
【问题描述】:

我有一个名为 df 的 pandas 数据框。它有一个名为article 的列。 article 列包含 600 个字符串,每个字符串代表一篇新闻文章。 我只想保留前四个句子包含关键字“COVID-19”AND(“China”或“Chinese”)的文章。但我无法自己找到一种方法来执行此操作。

(在字符串中,句子以\n分隔。示例文章如下所示:)

\nChina may be past the worst of the COVID-19 pandemic, but they aren’t taking any chances.\nWorkers in Wuhan in service-related jobs would have to take a coronavirus test this week, the government announced, proving they had a clean bill of health before they could leave the city, Reuters reported.\nThe order will affect workers in security, nursing, education and other fields that come with high exposure to the general public, according to the edict, which came down from the country’s National Health Commission.\ .......

【问题讨论】:

  • 您的意思是要删除该列中不包含这些单词的所有行吗?我从this question 假设您将首先将文章列减少到仅在过滤之前的前三四个句子?
  • 是的,我想删除该列中不包含这些单词的所有行,但我不想将文章列减少到仅前三四个句子。希望过滤后保留全文。 :)

标签: python pandas filter keyword-search


【解决方案1】:

首先我们定义一个函数来根据你的关键字是否出现在给定的句子中返回一个布尔值:

def contains_covid_kwds(sentence):
    kw1 = 'COVID19'
    kw2 = 'China'
    kw3 = 'Chinese'
    return kw1 in sentence and (kw2 in sentence or kw3 in sentence)

然后我们通过将此函数(使用Series.apply)应用于df.article 列的句子来创建一个布尔序列。

请注意,我们使用 lambda 函数来截断传递给contains_covid_kwds 的句子,直到第五次出现'\n',即您的前四个句子(有关其工作原理的更多信息here):

series = df.article.apply(lambda s: contains_covid_kwds(s[:s.replace('\n', '#', 4).find('\n')]))

然后我们将布尔序列传递给df.loc,以便本地化序列被评估为True的行:

filtered_df = df.loc[series]

【讨论】:

  • 感谢您的回答。你能详细说明s[:s.replace('\n', '#', 4)是什么意思吗?
  • s.replace('\n', '#', 4) 返回相同的字符串,但前 4 次出现的 '\n''#' 替换。替换符号不相关:我们只是这样做,因为然后我们在返回的字符串上使用.find('\n') 来查找下一个'\n' 所在的索引。由于我们刚刚替换了前 4 个'\n's,这为我们提供了第五个'\n' 的位置,也就是您的第四句结束的位置。然后我们简单地取这个索引并用s[:index_of_the_fifth_newline_char]分割原始字符串。
  • 这有点令人费解,因为我们需要对列中的每个元素执行这些操作,但 before 实际上将它们传递给contain_covid_kwds 函数。如果您事先执行“take-the-first-four-sentences-of-the-string”过滤器,则不需要这样做。
【解决方案2】:

您可以使用 pandas 的 apply 方法并按照我的方式进行操作。

string = "\nChina may be past the worst of the COVID-19 pandemic, but they aren’t taking any chances.\nWorkers in Wuhan in service-related jobs would have to take a coronavirus test this week, the government announced, proving they had a clean bill of health before they could leave the city, Reuters reported.\nThe order will affect workers in security, nursing, education and other fields that come with high exposure to the general public, according to the edict, which came down from the country’s National Health Commission."
df = pd.DataFrame({'article':[string]})

def findKeys(string):
    string_list = string.strip().lower().split('\n')
    flag=0
    keywords=['china','covid-19','wuhan']

    # Checking if the article has more than 4 sentences
    if len(string_list)>4:
        # iterating over string_list variable, which contains sentences.
        for i in range(4):
            # iterating over keywords list
            for key in keywords:
                # checking if the sentence contains any keyword
                if key in string_list[i]:
                    flag=1
                    break
    # Else block is executed when article has less than or equal to 4 sentences
    else:
        # Iterating over string_list variable, which contains sentences
        for i in range(len(string_list)):
            # iterating over keywords list
            for key in keywords:
                # Checking if sentence contains any keyword
                if key in string_list[i]:
                    flag=1
                    break
    if flag==0:
        return False
    else:
        return True

然后在df上调用pandas的apply方法:-

df['Contains Keywords?'] = df['article'].apply(findKeys)

【讨论】:

  • 但是您的代码没有对此做出响应 - “COVID-19” AND(“China” OR “Chinese”)
  • 您需要输入所有小写字母的关键字。我特意将所有内容都设为小写,以免因大小写差异而遗漏关键字
  • 这很聪明。但我的意思是应该保留一个包含中国或中国的字符串。这两个词的区别不是小写和大写
【解决方案3】:

首先,我创建一个系列,其中仅包含原始 `df['articles'] 列中的前四个句子,并将其转换为小写,假设搜索应该与大小写无关。

articles = df['articles'].apply(lambda x: "\n".join(x.split("\n", maxsplit=4)[:4])).str.lower()

然后使用简单的布尔掩码仅过滤在前四个句子中找到关键字的那些行。

df[(articles.str.contains("covid")) & (articles.str.contains("chinese") | articles.str.contains("china"))]

【讨论】:

    【解决方案4】:

    这里:

    found = []
    s1 = "hello"
    s2 = "good"
    s3 = "great"
    for string in article:
        if s1 in string and (s2 in string or s3 in string):
            found.append(string)
    

    【讨论】:

    • 条件(s2 or s3)对于非空字符串总是为真,无论这些字符串包含什么,..所以它并没有真正正确地检查它。应该是 (s2 in string or s3 in string)。此外,要检查的字符串位于数据框中:“我有一个名为 df 的 pandas 数据框。它有一个名为 article 的列”。
    • 对不起,我打错了。
    • 还是不正确。 in 的优先级高于or,因此它等同于s2 or (s3 in string),并且s2 再次将始终为True,因此检查s3 in string 变得无用。 Check it for yourself.
    猜你喜欢
    • 2022-12-05
    • 1970-01-01
    • 2011-05-14
    • 1970-01-01
    • 2017-08-03
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    • 2017-03-22
    相关资源
    最近更新 更多