使用 Pandas 过滤具有多个值的单元格中的字符串

Posted

技术标签:

【中文标题】使用 Pandas 过滤具有多个值的单元格中的字符串【英文标题】:Using Pandas to Filter String In Cell with Multiple Values 【发布时间】:2020-09-23 17:16:59 【问题描述】:

我正在使用 pandas 使用 str.contains() 过滤数据框,但我的逻辑是删除我可能希望在给定字符串的情况下保留的值。我不知道如何使用 Pandas 来解决这个问题。

我正在使用的 Excel 工作表中的示例单元格如下所示:

案例 #1:不要举报,因为有不同的收件人 bob@gmail.com

Recipient
---------
joe@work.com, bob@gmail.com, sally@work.com

案例#2:标记这个,因为每个收件人都包含@work.com

Recipient
---------
mike@work.com, taylor@work.com, barbra@work.com

我有一种情况,我只需要它来过滤是否出现特定值。 例如,如果“收件人”包含电子邮件 joe@work.com,则删除此值。但是,如果收件人列包含“joe@work.com,bob@gmail.com”(是的,值以逗号分隔,就像在单个单元格中那样。)并保留它。最终,此数据框将从最终报告中删除。所以我想删除只包含@work.com 的所有内容,但如果它包含@gmail.com、@work.com 则不要删除。

即使收件人列包含“gmail.com”,下面的此查询也会删除所有内容

df['EMAIL10'] = df['Type'].str.contains('Email') & df['Type'].str.contains(
                'Tracking | Data') & df[
                                'Recipient'].str.contains('@work.com') 

如果我需要澄清,请告诉我

【问题讨论】:

【参考方案1】:

您可以创建一个布尔掩码来指示all 单独的单词是否包含'@work'

首先,split 将每个单词放入一个单独的单元格中,explode 将把它变成一个大系列,索引重复并指向原始 DataFrame 的索引。 .str.contains 检查您的条件,all(level=0) 检查原始 DataFrame 中一行中的每个单词是否为真。

import pandas as pd

df = pd.DataFrame('col': ['joe@work.com, bob@gmail.com, sally@work.com', 
                           'mike@work.com, taylor@work.com, barbra@work.com'])

df['all_work'] = df['col'].str.split(', ').explode().str.contains('@work').all(level=0)

print(df)
                                               col  all_work
0      joe@work.com, bob@gmail.com, sally@work.com     False
1  mike@work.com, taylor@work.com, barbra@work.com      True

为了解释,在拆分和explode之后我们有:

df['col'].str.split(', ').explode()

 0       joe@work.com 
 0      bob@gmail.com   # Each item split separately
 0     sally@work.com
 1      mike@work.com
 1    taylor@work.com
 1    barbra@work.com
#|
#Index corresponds to Index of the original DataFrame

【讨论】:

这很好用。适合我现有的代码。没有明显的减速。非常感谢您的解释。学习了一些关于 .explode() 的新知识【参考方案2】:

我认为您可以使用explode 然后groupby 过滤掉@work 电子邮件

print(df)

                                         Recipient
0      joe@work.com, bob@gmail.com, sally@work.com
1  mike@work.com, taylor@work.com, barbra@work.com

s = df['Recipient'].str.split(',').explode()
df['flag removed'] = s[~s.str.contains('@work')].groupby(level=0).agg(','.join)

print(df)

                                         Recipient    flag removed
0      joe@work.com, bob@gmail.com, sally@work.com   bob@gmail.com
1  mike@work.com, taylor@work.com, barbra@work.com             NaN

您可以.dropna() 删除不匹配的行

【讨论】:

【参考方案3】:

如果您在 Python 中运行字符串处理,您应该会获得显着的速度优势:

df["all_work"] = [all("@work" in text for text in ent.split(","))
                  for ent in df.col ]

                 col                               all_work
0   joe@work.com, bob@gmail.com, sally@work.com     False
1   mike@work.com, taylor@work.com, barbra@work.com True

【讨论】:

【参考方案4】:

让我们试试str.count

df.col.str.count('@work.com')==df.col.str.count(',').add(1)
Out[148]: 
0    False
1     True
Name: col, dtype: bool

【讨论】:

以上是关于使用 Pandas 过滤具有多个值的单元格中的字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何将多个单元格中的字符串聚合到一个单元格中?

将 pandas 中的一个单元格拆分为多行

使用 .head() 方法更改 Pandas 中单元格中打印的文本数量 [重复]

如何从具有多个数组的字典中获取特定键并存储到放置在表格视图单元格中的字符串中

将单元格中的字符串拆分为不同的行,pandas [关闭]

将字符串值分配给pandas中的单元格