Python实现R的lapply等价功能:清洗手机号并生成新列
当然可以!在Python的pandas生态里,我们完全可以实现和你R中data.table的lapply(.SD, ...)等价的批量处理效果,写法还挺简洁的。下面直接给你对应代码和解释:
Python 等价实现方案
首先,我们先还原你给出的示例DataFrame,方便测试:
import pandas as pd import numpy as np # 构建示例DataFrame data = { 'kac': [5004490, 5003807], 'play_id': [20002075, '00601731'], 'phone1': ['0900031349', np.nan], 'phone2': ['090891349', np.nan], 'phone3': [np.nan, np.nan], 'phone4': [np.nan, np.nan], 'phone5': [np.nan, '088235311'], 'phone6': [np.nan, np.nan], 'phone7': [np.nan, np.nan] } df = pd.DataFrame(data)
接下来是核心的批量清洗逻辑,这里有两种简洁的实现方式:
方法1:自定义清洗函数 + applymap 批量处理
这种方式和你R中自定义匿名函数的思路完全对应,可读性强:
# 定义原列和目标新列的名称列表 original_phone_cols = [f"phone{i}" for i in range(1, 8)] new_phone_cols = [f"ph{i}" for i in range(1, 8)] # 定义手机号清洗函数:去除空格、/、-、+ 字符 def clean_phone_number(phone_str): if pd.isna(phone_str): return phone_str # 保留空值 import re # 正则匹配所有需要移除的字符,替换为空字符串 return re.sub(r"[\s/\-+]", "", str(phone_str)) # 对指定列批量应用清洗函数,生成新列 df[new_phone_cols] = df[original_phone_cols].applymap(clean_phone_number)
方法2:用pandas原生replace 一步到位
如果追求更简洁的写法,pandas的replace支持正则批量替换,代码更短:
# 同样定义列名列表 original_phone_cols = [f"phone{i}" for i in range(1, 8)] new_phone_cols = [f"ph{i}" for i in range(1, 8)] # 直接对指定列批量替换目标字符 df[new_phone_cols] = df[original_phone_cols].replace(r"[\s/\-+]", "", regex=True)
验证结果
运行上述代码后,打印处理后的DataFrame就能看到效果:
print(df)
输出结果:
kac play_id phone1 phone2 phone3 phone4 phone5 phone6 phone7 ph1 ph2 ph3 ph4 ph5 ph6 ph7 0 5004490 20002075 0900031349 090891349 NaN NaN NaN NaN NaN 0900031349 090891349 NaN NaN NaN NaN NaN 1 5003807 00601731 NaN NaN NaN NaN 088235311 NaN NaN NaN NaN NaN NaN 088235311 NaN NaN
补充说明
你提到用do.call遇到问题,其实Python中的do.call和R里的用法差异较大,而上面两种方法都是pandas中处理批量列的惯用写法,更符合Python的代码风格,也更直观。
内容的提问来源于stack exchange,提问作者Tilo
相关产品推荐
相关产品推荐

