升级Pandas至2.1.4后dropna失效致数值转换报错求助
Pandas版本升级后dropna失效导致解析"nan"报错问题
问题场景
原始输入Dataframe
1 | 2 -------|------- 123 | 123 456 | 456 NaN | 789
目标转换格式
list_number | item_code ------------|---------- 1 | 123 1 | 456 2 | 123 2 | 456 2 | 789
报错信息
ValueError: Unable to parse string "nan"
问题代码片段
df = # my data df.dropna(axis=1, how='all', inplace=True) df = pd.melt(df, var_name='LIST_NUMBER', value_name='ITEM_CODE') df["LIST_NUMBER"] = pd.to_numeric( df["LIST_NUMBER"].astype(str).str.replace(r"[^\d]", ""), errors='raise') df["ITEM_CODE"] = pd.to_numeric( df["ITEM_CODE"].astype(str).str.replace(r"[^\d]", ""), errors='raise')
补充信息:pd.melt后的Dataframe
list_number | item_code ------------|---------- 1 | 123 1 | 456 1 | NaN 2 | 123 2 | 456 2 | 789
此前代码在Pandas 1.4.4下运行正常,升级至2.1.4后触发报错,且dropna(axis=1, how='all')未产生预期效果(未移除包含NaN的列)。
问题原因
- dropna参数的本质误解:
dropna(axis=1, how='all')的作用是删除整列所有值均为NaN的列,你的原始Dataframe第一列包含两个有效值,仅一个NaN,因此无论哪个版本都不会删除该列。之前旧版本运行正常,大概率是当时的季度数据第一列全为NaN,或存在其他未察觉的差异。 - Pandas 2.0+对NaN转字符串的行为变更:在Pandas 1.x版本中,NaN转字符串可能返回空字符串;但2.0+版本统一将NaN转为字符串"nan"。后续代码中
str.replace(r"[^\d]", "")会将"nan"处理为空字符串,而pd.to_numeric(..., errors='raise')无法解析空字符串,因此抛出报错。
解决方案
方案1:先移除无效行再转换数值(符合目标格式需求)
先删除ITEM_CODE为NaN的行,再执行数值转换,完全匹配你的目标输出:
df = # 你的原始数据 df = pd.melt(df, var_name='LIST_NUMBER', value_name='ITEM_CODE') # 移除ITEM_CODE为空的行 df = df.dropna(subset=['ITEM_CODE']) # 转换为数值类型 df["LIST_NUMBER"] = pd.to_numeric( df["LIST_NUMBER"].astype(str).str.replace(r"[^\d]", ""), errors='raise') df["ITEM_CODE"] = pd.to_numeric( df["ITEM_CODE"].astype(str).str.replace(r"[^\d]", ""), errors='raise')
方案2:容错式数值转换(保留行但处理无效值)
如果需要保留行,可将pd.to_numeric的errors参数设为'coerce',将无法解析的值转为NaN,后续按需处理:
df = # 你的原始数据 df = pd.melt(df, var_name='LIST_NUMBER', value_name='ITEM_CODE') # 转换时自动将无效值转为NaN df["LIST_NUMBER"] = pd.to_numeric( df["LIST_NUMBER"].astype(str).str.replace(r"[^\d]", ""), errors='coerce') df["ITEM_CODE"] = pd.to_numeric( df["ITEM_CODE"].astype(str).str.replace(r"[^\d]", ""), errors='coerce') # 按需删除NaN行 df = df.dropna()
方案3:修正dropna参数(若需删除含NaN的列)
如果你的初衷是删除所有包含NaN的列,需将how='all'改为how='any',但此操作会删除所有存在NaN的列,需确认是否符合业务需求:
df.dropna(axis=1, how='any', inplace=True) df = pd.melt(df, var_name='LIST_NUMBER', value_name='ITEM_CODE') # 后续转换代码...
内容的提问来源于stack exchange,提问作者SRJCoding
相关产品推荐
相关产品推荐

