You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用.apply()清洗DataFrame邮箱:数据未更新问题

很高兴看到你已经修正代码让.apply()生效了!既然你想继续用.apply()来巩固这个方法,同时也想了解更高效的替代方案,我来帮你一步步梳理:

一、优化后的.apply()写法

首先要修正一个小细节:你原来的domains是一个完整字符串,得拆分成列表才能逐个遍历检查域名:

domains = 'gmail.com hotmail.com yahoo.com hotmail.co.uk'.split()

然后调整清洗函数,找到匹配的域名后就直接处理返回,避免不必要的循环:

def cleaning(email):
    for domain in domains:
        if domain in email:
            # 检查域名前一位是不是@
            if email[-len(domain)-1] != '@':
                # 拆分用户名和域名,拼接@
                username = email[:-len(domain)]
                return f"{username}@{domain}"
    # 如果没有匹配到域名或者已经有@,直接返回原邮箱
    return email

调用.apply()处理邮箱列:

df['email'] = df['email'].apply(cleaning)
print(df)

输出结果会完全符合你的预期:

email    col2
0    foobar@gmail.com    make
1    barfoo@gmail.com      a
2  hellothere@gmail.com   data
3  myemail@hotmail.com  frame

二、更高效的非.apply()方案:正则表达式

.apply()是逐行处理,当DataFrame数据量很大时,效率会比较低。用Pandas的字符串方法结合正则表达式,能实现向量级别的处理,速度快很多:

import re

# 构造正则模式:匹配域名且前面没有@
domain_pattern = r'(?<!@)(gmail\.com|hotmail\.com|yahoo\.com|hotmail\.co\.uk)'
df['email'] = df['email'].str.replace(domain_pattern, r'@\1', regex=True)

正则解释:

  • (?<!@):负向零宽断言,确保匹配到的域名前面没有@符号
  • (gmail\.com|...):分组匹配所有目标域名(注意.要转义成\.,否则会匹配任意字符)
  • r'@\1':替换为@加上分组匹配到的域名

这个方法和.apply()的结果完全一致,但处理大数据集时性能会好很多。

三、为什么最初的函数没生效?

结合你提到的@Tomaz Gandor指出的错误,大概率是因为domains没有拆分成列表——原来的写法会让循环遍历字符串的每个字符,而不是逐个域名检查,所以函数找不到匹配的域名,自然不会修改邮箱。修正后就能正常工作啦~

内容的提问来源于stack exchange,提问作者SCool

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:07:13