从含字符串及NaN值的DataFrame中提取最大数值的优化与适配
问题解答
背景
现有示例DataFrame:
import pandas as pd import numpy as np data = pd.DataFrame(['random 15 numbers 128 and 12 letters','12-5','page 65'], columns=['text'])
需求为提取字符串中的所有数字,将最大值写入新列。当前实现代码如下:
data['list']=data['text'].str.extractall('(\d+)').unstack().values.tolist() data['max']=data['list'].apply(lambda row:max([int(x) for x in row if x is not np.nan]))
需解决两个问题:
- 是否存在更优雅的实现方式?
- 当前代码无法适配含NaN的原DataFrame,需修改代码,让原DataFrame含NaN时对应结果列也为NaN;同时适配不含数字的字符串,此时结果列为NaN。测试用例:
data = pd.DataFrame(['random 15 numbers 128 and 12 letters','12-5','page 65',np.nan], columns=['text'])
问题1:更优雅的实现方式
推荐使用pandas链式操作风格,无需额外中间列,逻辑更清晰:
data['max_num'] = ( data['text'] .str.findall(r'\d+') # 提取所有数字字符串,返回列表/NaN .explode() # 将列表拆分为行,保留原索引 .apply(pd.to_numeric, errors='coerce') # 转为数值型,无效值转NaN .groupby(level=0) # 按原行索引分组 .max() # 取每组最大值,无数据则返回NaN )
这种方式完全利用pandas内置方法处理,避免手动遍历和NaN判断,可读性与维护性更强。
问题2:适配NaN和无数字的场景
上述链式写法已天然适配所有场景:
- 原
text列是NaN时,str.findall返回NaN,后续操作会保留该NaN,最终结果为NaN - 字符串无数字时,
str.findall返回空列表,explode后该索引无数据,groupby.max()自动返回NaN
测试扩展用例(新增无数字字符串):
data = pd.DataFrame( ['random 15 numbers 128 and 12 letters','12-5','page 65',np.nan, 'no numbers here'], columns=['text'] ) data['max_num'] = ( data['text'] .str.findall(r'\d+') .explode() .apply(pd.to_numeric, errors='coerce') .groupby(level=0) .max() )
输出结果:
| text | max_num |
|---|---|
| random 15 numbers 128 and 12 letters | 128.0 |
| 12-5 | 12.0 |
| page 65 | 65.0 |
| NaN | NaN |
| no numbers here | NaN |
如果偏好自定义函数的方式,可明确处理边界情况:
import re def extract_max_num(s): if not isinstance(s, str): return np.nan num_strs = re.findall(r'\d+', s) return max(map(int, num_strs)) if num_strs else np.nan data['max_num'] = data['text'].apply(extract_max_num)
内容的提问来源于stack exchange,提问作者principal-ideal-domain
相关产品推荐
相关产品推荐

