【问题标题】:Reading decimal representation floats from a CSV with pandas从带有熊猫的 CSV 中读取十进制表示
【发布时间】:2020-11-22 00:39:07
【问题描述】:

我正在尝试读取 CSV 文件的内容,该文件包含我认为是 IEEE 754 单精度浮点数的十进制格式。

默认情况下,它们以 int64 格式读入。如果我用dtype = {'col1' : np.float32} 之类的东西指定数据类型,则dtype 会正确显示为float32,但它们与float 而不是int 的值相同,即。 1079762502 变为 1.079763e+09 而不是 3.435441493988037

我已设法使用以下任一方法对单个值进行转换:

from struct import unpack

v = 1079762502

print(unpack('>f', v.to_bytes(4, byteorder="big")))
print(unpack('>f', bytes.fromhex(str(hex(v)).split('0x')[1])))

哪个产生

(3.435441493988037,)
(3.435441493988037,)

但是,我似乎无法使用 pandas 以矢量化方式实现这一点:

import pandas as pd
from struct import unpack

df = pd.read_csv('experiments/test.csv')

print(df.dtypes)
print(df)

df['col1'] = unpack('>f', df['col1'].to_bytes(4, byteorder="big"))
#df['col1'] = unpack('>f', bytes.fromhex(str(hex(df['col1'])).split('0x')[1]))

print(df)

抛出以下错误

col1    int64
dtype: object
         col1
0  1079762502
1  1079345162
2  1078565306
3  1078738012
4  1078635652

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-c06d0986cc96> in <module>
      7 print(df)
      8 
----> 9 df['col1'] = unpack('>f', df['col1'].to_bytes(4, byteorder="big"))
     10 #df['col1'] = unpack('>f', bytes.fromhex(str(hex(df['col1'])).split('0x')[1]))
     11 

~/anaconda3/envs/test/lib/python3.7/site-packages/pandas/core/generic.py in __getattr__(self, name)
   5177             if self._info_axis._can_hold_identifiers_and_holds_name(name):
   5178                 return self[name]
-> 5179             return object.__getattribute__(self, name)
   5180 
   5181     def __setattr__(self, name, value):

AttributeError: 'Series' object has no attribute 'to_bytes'

或者如果我尝试第二种方式,TypeError: 'Series' object cannot be interpreted as an integer

我在这里的 Python 知识有限,我想我可以遍历每一行,转换为十六进制,然后转换为字符串,然后剥离 0x,解压缩并存储。但这似乎非常复杂,在较小的样本数据集上已经花费了几秒钟,更不用说数十万个条目了。我在这里遗漏了一些简单的东西,有没有更好的方法?

【问题讨论】:

    标签: python pandas numpy csv ieee-754


    【解决方案1】:

    CSV 是一种文本格式,IEEE 754 单精度浮点数是二进制数字格式。如果你有 CSV,你有文本,它根本不是那种格式。如果我理解正确,我认为您的意思是您有代表整数(十进制格式)的文本,对应于您的 32 位浮点数的 32 位整数解释。

    因此,对于初学者来说,当您从 csv 读取数据时,pandas 默认使用 64 位整数。因此转换为 32 位整数,然后使用 .view 重新解释字节:

    In [8]: df
    Out[8]:
             col1
    0  1079762502
    1  1079345162
    2  1078565306
    3  1078738012
    4  1078635652
    
    In [9]: df.col1.astype(np.int32).view('f')
    Out[9]:
    0    3.435441
    1    3.335940
    2    3.150008
    3    3.191184
    4    3.166780
    Name: col1, dtype: float32
    

    分解成步骤帮助理解:

    In [10]: import numpy as np
    
    In [11]: arr = df.col1.values
    
    In [12]: arr
    Out[12]: array([1079762502, 1079345162, 1078565306, 1078738012, 1078635652])
    
    In [13]: arr.dtype
    Out[13]: dtype('int64')
    
    In [14]: arr_32 = arr.astype(np.int32)
    
    In [15]: arr_32
    Out[15]:
    array([1079762502, 1079345162, 1078565306, 1078738012, 1078635652],
          dtype=int32)
    
    In [16]: arr_32.view('f')
    Out[16]:
    array([3.4354415, 3.33594  , 3.1500077, 3.191184 , 3.1667795],
          dtype=float32)
    

    【讨论】:

    • 啊,对了。 .view 是我想要让它以我想要的格式实际表示值的魔法,非常感谢。我现在可以在读入数据时简单地使用dtype = {'col1' : np.int32},并设置df['col1'] = df['col1'].view('f') 来获取一列32 位浮点数,这要简单得多。
    猜你喜欢
    • 2018-10-03
    • 2020-12-23
    • 2020-08-12
    • 1970-01-01
    • 2014-01-14
    • 2016-03-11
    • 1970-01-01
    • 1970-01-01
    • 2021-04-29
    相关资源
    最近更新 更多