如何用正则高效替换非数字字符并筛选Pandas Series非空非空格值
优化正则提取数字与高效筛选Pandas Series的方案
我来帮你优化现有的代码,解决正则匹配的准确性问题,同时提升处理大数据集时的效率~
首先看你的需求:要提取字符串里的数字(包括小数点,从期望结果里的119.45能看出来),然后筛选掉处理后为空或全是空格的无效值。现有代码有两个可以改进的地方:一是正则没考虑保留小数点,二是用apply逐行处理效率偏低,筛选逻辑也可以简化。
第一步:用矢量化操作替换正则提取
原代码用apply(lambda x: re.sub(...))是逐行处理,对于大数据集来说效率不高。Pandas的str.replace是矢量化方法,底层用C实现,速度快很多。另外,你的期望结果里保留了小数点,所以正则要调整为保留数字和小数点,同时可以额外处理多个小数点的情况(比如如果有12.34.56,只保留第一个小数点)。
代码示例:
import pandas as pd # 构造你的示例数据 df = pd.DataFrame({ 'id': [ 'B-27000', '44-11-E', 'LAND-11-4', '17772A', '88LL9A', '321LP-3', 'UNIT 9', 'CAM -00-12', 'WWcard_055_34QE', 'EE119.45', 'aaa', 'b', 'b' ] }) # 提取数字和小数点,移除其他所有字符 df['numeric_no'] = df['id'].str.replace(r'[^0-9.]', '', regex=True) # 可选:如果有多个小数点,只保留第一个(比如处理"12.34.56"变成"12.3456") df['numeric_no'] = df['numeric_no'].str.replace(r'(\..*)\.', r'\1', regex=True)
第二步:高效筛选有效值
原筛选逻辑(df['numeric_no'] != '') & (df['numeric_no'] != ' ')有点冗余,因为处理后的numeric_no如果是全空格,str.strip()后会变成空字符串。更严谨的是,我们要筛选出至少包含一个数字的行(避免出现只有小数点的无效值),用str.contains矢量化判断效率很高。
两种筛选方式可选:
方式一:简单判断非空(适合确定处理后不会只有小数点的情况)
df = df[df['numeric_no'].str.strip() != '']
方式二:严谨判断包含数字(推荐)
df = df[df['numeric_no'].str.contains(r'\d', regex=True)]
完整代码与结果
把两步结合起来,完整代码运行后就能得到你想要的结果:
import pandas as pd df = pd.DataFrame({ 'id': [ 'B-27000', '44-11-E', 'LAND-11-4', '17772A', '88LL9A', '321LP-3', 'UNIT 9', 'CAM -00-12', 'WWcard_055_34QE', 'EE119.45', 'aaa', 'b', 'b' ] }) # 提取数字(含小数点) df['numeric_no'] = df['id'].str.replace(r'[^0-9.]', '', regex=True) # 处理多余小数点 df['numeric_no'] = df['numeric_no'].str.replace(r'(\..*)\.', r'\1', regex=True) # 筛选有效行 df = df[df['numeric_no'].str.contains(r'\d', regex=True)] print(df['numeric_no'])
输出结果:
0 27000 1 4411 2 114 3 17772 4 889 5 3213 6 9 7 0012 8 05534 9 119.45 Name: numeric_no, dtype: object
效率提升的关键点
- 用
str.replace替代apply(lambda x: re.sub(...)):矢量化操作避免了Python层面的逐行循环,数据量越大,效率提升越明显。 - 筛选逻辑用矢量化方法:
str.contains和str.strip都是Pandas优化过的方法,比手动逐行判断快很多。
内容的提问来源于stack exchange,提问作者daiyue
相关产品推荐
相关产品推荐

