You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级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的列)。


问题原因

  1. dropna参数的本质误解:dropna(axis=1, how='all')的作用是删除整列所有值均为NaN的列,你的原始Dataframe第一列包含两个有效值,仅一个NaN,因此无论哪个版本都不会删除该列。之前旧版本运行正常,大概率是当时的季度数据第一列全为NaN,或存在其他未察觉的差异。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 20:29:50