Pandas Series从object转float64:部分值变NaN的原因及解决
首先还原你的场景:你有一个名为energy["Energy Supply"]的Series,当前类型是object,数据如下:
Country China 127191 United States 90838 Japan 18984 United Kingdom 7920 Russian Federation 30709 Canada 10431 Germany 13261 India 33195 France 10597 South Korea 11007 Italy 6530 Spain 4923 Iran NaN Australia 5386 Brazil 12149 Name: Energy Supply, dtype: object
你提到之前通过代码将"..."替换为np.NaN,现在想把整个Series转为float64类型,但使用pd.to_numeric(energy["Energy Supply"], errors='coerce')后,部分数值(比如127191、90838)变成了NaN,而另一些数值(30709、10431)却保留了下来。下面来分析原因和解决办法:
核心原因分析
为什么Series是object类型?
你说“检查发现每个数值都是float类型”,这里大概率是误解——如果Series的dtype是object,说明它的元素类型是混合的:可能一部分是字符串(比如看起来像数字的"127191"),另一部分是float类型的NaN。当一个Series中存在多种数据类型时,Pandas会将其整体标记为object类型。为什么部分数值转成了NaN?
pd.to_numeric(errors='coerce')会把无法解析为数字的内容转为NaN。那些被转成NaN的“数值”,实际上是带有隐藏非数字字符的字符串——比如前后空格、制表符、全角数字(比如127191),或者其他你肉眼看不到的Unicode字符。而保留下来的数值,要么是已经是float类型,要么是没有隐藏字符的纯数字字符串。
解决步骤
第一步:排查隐藏字符
先确认哪些元素是问题字符串,以及它们的具体内容:
# 查看每个元素的实际类型 print(energy["Energy Supply"].apply(type)) # 筛选非NaN的元素,检查是否包含非数字字符 mask = energy["Energy Supply"].notna() problem_rows = energy.loc[mask, "Energy Supply"].str.contains(r'\D', na=False) print(energy.loc[problem_rows])
这段代码会帮你找出那些包含非数字字符(\D代表非数字)的行,比如带空格的" 127191 "就会被检测出来。
第二步:清理数据并转换类型
针对隐藏字符的问题,先做数据清洗,再转换类型:
import pandas as pd import numpy as np # 处理字符串类型的元素:去除前后空格,处理全角转半角(如果有) def clean_numeric_str(x): if isinstance(x, str): # 去除前后空格 x = x.strip() # 全角数字转半角(如果需要) x = x.translate(str.maketrans('0123456789', '0123456789')) return x energy["Energy Supply"] = energy["Energy Supply"].apply(clean_numeric_str) # 现在再转换为数值类型 energy["Energy Supply"] = pd.to_numeric(energy["Energy Supply"], errors='coerce')
第三步:验证结果
转换完成后,你可以用以下代码确认类型和数据:
print(energy["Energy Supply"].dtype) # 应该输出float64 print(energy["Energy Supply"]) # 查看所有数值是否正常保留
内容的提问来源于stack exchange,提问作者Lumi Wang

