使用 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 过滤具有多个值的单元格中的字符串的主要内容,如果未能解决你的问题,请参考以下文章
使用 .head() 方法更改 Pandas 中单元格中打印的文本数量 [重复]