使用 pandas 从 CSV 中读取十进制表示浮点数
Reading decimal representation floats from a CSV with pandas
我正在尝试读取 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,解压并存储。但这看起来非常复杂,并且在较小的样本数据集上已经花费了几秒钟,更不用说数十万个条目了。我是否遗漏了一些简单的东西,有没有更好的方法?
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)
我正在尝试读取 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,解压并存储。但这看起来非常复杂,并且在较小的样本数据集上已经花费了几秒钟,更不用说数十万个条目了。我是否遗漏了一些简单的东西,有没有更好的方法?
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)