Pandas宽表转长表后Millisec_diff列小数丢失变为整数的问题求助
你好!我来帮你分析下这个问题可能的原因和对应的排查/解决办法:
大概率是数据读取时的类型推断问题
这是pandas处理大文件时很常见的小坑:当你用pd.read_csv()读取全量40K行的文件时,pandas会自动推断每列的数据类型。如果你的全量数据里Millisec_diff列有大量整数形式的行(比如0,1,2这类),pandas可能会把整个列的类型推断为整数类型(int64),而样本数据因为小数占比高,被推断为浮点数类型(float64),这就导致全量数据的小数部分直接被截断了。
具体排查和解决步骤
1. 先确认原始数据的类型
读取全量数据后,先执行以下代码,看看Millisec_diff列的实际类型和前几行值:
print("列数据类型:", df['Millisec_diff '].dtype) print("前10行值:") print(df[['Millisec_diff ']].head(10))
如果输出的类型是int64,那就是读取时的类型推断错误,直接在读取CSV时指定该列的类型为浮点数即可:
# 注意列名要和你实际的列名完全一致(包括末尾的空格) df = pd.read_csv('你的全量文件.csv', dtype={'Millisec_diff ': float})
2. 排除显示设置的问题
如果原始数据的类型是float64,但melt后显示为整数,可能是pandas的浮点数显示格式被默认简化了。可以临时修改显示格式验证:
import pandas as pd # 强制显示4位小数 pd.options.display.float_format = '{:.4f}'.format print(df_long['Millisec_diff '].head(20))
如果这样能看到原本的小数,说明数据本身是正确的,只是显示的问题,不需要修改数据,调整显示格式即可。
3. 确认列名的一致性
你的代码里id_vars写的是'Millisec_diff '(末尾带空格),但要确保全量数据的列名确实带这个空格!可以用以下代码输出所有列名:
print("所有列名:", df.columns.tolist())
如果列名实际是Millisec_diff(无空格),那你代码里的空格会导致引用了一个不存在的列(不过这种情况一般会填充NaN,和你描述的整数情况不符,但还是要确认下)。
4. 定位问题发生的阶段
可以在执行melt前后分别检查Millisec_diff列的值,缩小问题范围:
# melt前检查 print("melt前的Millisec_diff值:") print(df[['Millisec_diff ']].sample(10)) # 执行melt df_long = pd.melt(df, id_vars=["time", 'Millisec_diff '], value_vars=col_names, var_name='param', value_name='value') # melt后检查 print("melt后的Millisec_diff值:") print(df_long['Millisec_diff '].sample(10))
如果melt前的值是正确的小数,melt后变成整数,那可能是melt操作的异常(但这个概率极低,样本数据正常的话基本可以排除)。
总结
最可能的根源是全量数据读取时的类型推断错误,指定dtype参数强制该列为浮点数就能解决问题。如果是显示问题,调整pandas的浮点数显示格式即可。
内容来源于stack exchange

