Pandas时间序列转换为float后仍显示NaN的问题排查
嘿,我来帮你捋捋这个问题哈~你已经做了不少步骤,但最后创建的时间序列里Speed列还是大量NaN,大概率是这几个地方出了问题:
可能的原因分析
1. 转float前的缺失值检查没覆盖所有情况
你在步骤2做的assert not bus1354['Speed'].isnull().any()是在把Speed转成float之前执行的,但这时候Speed是字符串类型(object),isnull()只能识别真正的NaN/空值,没法识别那些非数字的字符串(比如"N/A"、"--"、空字符串""这些)。这些“伪装”成正常值的字符串,等到你用apply(float)转换时,就会被强制转成NaN,最后导致时间序列里全是缺失值。
2. Timestamp的截断逻辑不对(和你想要的“hh:mm:ss”不符)
你注释说要把Timestamp截断到hh:mm:ss,但代码里写的是x[:7]——这会取字符串的前7个字符,完全不是你要的时间部分啊!举个例子:
- 如果原Timestamp是
"2024-06-01 14:30:00",x[:7]会得到"2024-06",转成datetime后是当月第一天的0点,根本不是时间部分; - 如果原Timestamp是纯时间字符串
"14:30:00",x[:7]会得到"14:30:0"(长度是8,前7个字符少了最后一位秒数),这是不合法的时间格式,pd.to_datetime会把它转成NaT(时间类型的缺失值)。
要是Timestamp列里有大量NaT,用它当索引创建Series时,对应的Speed值自然就显示成NaN了。
3. 索引和数据的隐性对齐问题(概率较低)
虽然你是从同一个DataFrame取的Speed和Timestamp,但如果在步骤4到7之间不小心修改了行顺序(比如排序、过滤),就可能导致索引和数据对不上,出现NaN。不过这种情况除非你做了额外操作,不然概率不高。
对应的解决办法
针对原因1:把所有非数字的“坑”都填上
别再手动替换空格了,直接用pd.to_numeric一步处理所有非数字的情况:
# 把所有无法转成数字的字符串直接转成NaN bus1354['Speed'] = pd.to_numeric(bus1354['Speed'], errors='coerce') # 把NaN替换成0(如果业务上允许的话) bus1354['Speed'].fillna(0, inplace=True) # 再检查有没有漏网的缺失值 assert not bus1354['Speed'].isnull().any()
这样不管是空格、"N/A"还是其他奇怪的符号,都能被处理掉,转成float后就不会突然冒NaN了。
针对原因2:修正Timestamp的转换逻辑
要提取hh:mm:ss,得根据原Timestamp的格式来调整:
- 如果原Timestamp是“日期+时间”的格式(比如
"2024-06-01 14:30:00"),提取时间部分:bus1354['Timestamp'] = pd.to_datetime(bus1354['Timestamp'].str.split().str[1]) - 如果原Timestamp就是纯时间字符串(比如
"14:30:00"),直接转成datetime就行,不用截断:bus1354['Timestamp'] = pd.to_datetime(bus1354['Timestamp'], format='%H:%M:%S')
转完之后记得检查有没有NaT:
assert not bus1354['Timestamp'].isna().any()
针对原因3:一步到位创建时间序列
别手动取列再拼Series了,直接用set_index方法,确保索引和数据绝对对齐:
bs1354Ser = bus1354.set_index('Timestamp')['Speed']
验证步骤
你可以按这个顺序重新操作,一步步排查:
- 先用
pd.to_numeric处理Speed列,确保没有隐藏的非数字值; - 修正Timestamp的转换逻辑,确认没有
NaT; - 用
set_index直接生成时间序列; - 查看
bs1354Ser.head()和bs1354Ser.isnull().sum(),看看缺失值是不是消失了。
这样应该就能解决你的问题啦~
内容的提问来源于stack exchange,提问作者ragzputin

