鉴于一个充满电子邮件的数据框,我想过滤出包含可能被阻止的域名或明显伪造的电子邮件的行。下面的数据框代表了我的数据示例。
>> print(df)
email number
1 fake@fake.com 2
2 real.email@gmail.com 1
3 no.email@email.com 5
4 real@yahoo.com 2
5 rich@money.com 1
我想按两个列表进行过滤。第一个列表是fake_lst = ['noemail', 'noaddress', 'fake', ... 'no.email']
。
第二个列表只是将集合from disposable_email_domains import blocklist
转换为列表(或保留为集合)。
当我使用df = df[~df['email'].str.contains('noemail')]
时,它可以正常工作并过滤掉该条目。然而,当我做df = df[~df['email'].str.contains(fake_lst)]
时,我得到TypeError: unhashable type: 'list'
。
显而易见的答案是,像在其他许多Filter Pandas Dataframe based on List of substrings或pandas filtering using isin function这样的stackoverflow问题中一样,使用df = df[~df['email'].isin(fake_lst)]
,但最终没有效果。
我想我可以为每个可能的列表条目使用str.contains('string')
,但这很麻烦。
因此,我需要根据两个列表中包含的子字符串来过滤此数据帧,以便删除任何包含要删除的特定子字符串的电子邮件以及包含该子字符串的后续行。
在上面的示例中,过滤后的数据帧为:
>> print(df)
email number
2 real.email@gmail.com 1
4 real@yahoo.com 2
5 rich@money.com 1
答案 0 :(得分:1)
如果您关注df
和fake_lst
df = pd.DataFrame({
'email': ['fake@fake.com', 'real.email@gmail.com', 'no.email@email.com',
'real@yahoo.com', 'rich@money.com'],
'number': [2, 1, 5, 2, 1]
})
fake_lst = ['fake', 'money']
选项1:
使用fake_lst
过滤电子邮件中包含任何apply
个单词的行:
df.loc[
~df['email'].apply(lambda x: any([i in x for i in fake_lst]))
]
email number
1 real.email@gmail.com 1
2 no.email@email.com 5
3 real@yahoo.com 2
选项2:
过滤掉没有apply
df.loc[
[not any(i) for i in zip(*[df['email'].str.contains(word) for word in fake_lst])]
]
email number
1 real.email@gmail.com 1
2 no.email@email.com 5
3 real@yahoo.com 2
答案 1 :(得分:0)
使用DataFrame.isin检查DataFrame中的每个元素是否包含在值中。另一个问题是,假列表中包含不带域名的名称,因此您需要str.split来删除与之不匹配的字符。
注意:str.contains测试模式或正则表达式是否包含在Series的字符串中,因此您的代码df ['email']。str.contains('noemail')工作正常,但不适用于列表
df[~df['email'].str.split('@').str[0].isin(fake_lst)]
email number
0 fake@fake.com 2
1 real.email@gmail.com 1
3 real@yahoo.com 2
4 rich@money.com 1