如何在Pandas中当正则表达式匹配时将值替换为np.nan
解决Pandas中匹配正则表达式后替换为NaN的问题
测试数据
先定义测试用的DataFrame:
import pandas as pd import numpy as np d_test = { 'latitude' : [40.765004, 45.504641, 40.00000, -34.283007], 'longitude' : [-73.965961, 122.000000, -90.121679, -118.439891], 'test': [1,2,3,4], } df_test = pd.DataFrame(d_test)
需求
使用正则表达式 r'^[+-]?[0-9]*[.][0]*?$' 匹配latitude和longitude列中的值,将匹配成功的单元格替换为np.nan,最终得到如下结果:
latitude longitude test 0 40.765004 -73.965961 1 1 NaN NaN 2 2 NaN -90.121679 3 3 -34.283007 -118.439891 4
(注:原需求示例中第2行longitude的NaN为笔误,实际该值-90.121679不匹配正则,应保留)
遇到的问题
之前尝试用where方法时出现报错:
属性错误:“DataFrame”对象没有“str”属性
原因是直接对DataFrame调用str属性,但str是Pandas Series专属方法,不能直接用于DataFrame。
解决方案
方法一:使用astype(str)+str.contains生成掩码,再用mask替换
# 指定要处理的列 target_cols = ['latitude', 'longitude'] # 生成布尔掩码:匹配正则表达式的单元格标记为True match_mask = df_test[target_cols].astype(str).str.contains(r'^[+-]?[0-9]*[.][0]*?$', regex=True) # 将掩码中为True的单元格替换为NaN df_test[target_cols] = df_test[target_cols].mask(match_mask)
方法二:使用applymap逐元素处理
target_cols = ['latitude', 'longitude'] # 定义匹配函数,判断单个值是否符合正则 def is_match(val): return pd.Series.str.contains(str(val), r'^[+-]?[0-9]*[.][0]*?$', regex=True) # 对指定列应用匹配,将匹配到的值替换为NaN df_test[target_cols] = df_test[target_cols].where(~df_test[target_cols].applymap(is_match))
执行上述任意一种方法后,即可得到符合需求的DataFrame。
内容的提问来源于stack exchange,提问作者illuminato
相关产品推荐
相关产品推荐

