在将 HDF 5 文件读入 Pandas 时,如何避免字符串被读取为字节?
how do I avoid strings being read as bytes when reading a HDF 5 file into Pandas?
目前h5文件中的数据没有前缀'b'。我用下面的代码读取了 h5 文件。我想知道是否有更好的方法来阅读 h5 并且没有前缀 'b'.
import tables as tb
import pandas as pd
import numpy as np
import time
time0=time.time()
pth='d:/download/'
# read data
data_trading=pth+'Trading_v01.h5'
filem=tb.open_file(data_trading,mode='a',driver="H5FD_CORE")
tb_trading=filem.get_node(where='/', name='wind_data')
df=pd.DataFrame.from_records(tb_trading[:])
time1=time.time()
print('\ntime on reading data %6.3fs' %(time1-time0))
# in python3, remove prefix 'b'
df.loc[:,'Date']=[[dt.decode('utf-8')] for dt in df.loc[:,'Date']]
df.loc[:,'Code']=[[cd.decode('utf-8')] for cd in df.loc[:,'Code']]
time2=time.time()
print("\ntime on removing prefix 'b' %6.3fs" %(time2-time1))
print('\ntotal time %6.3fs' %(time2-time0))
时间的结果
time on reading data 1.569s
time on removing prefix 'b' 29.921s
total time 31.490s
你看,去掉前缀'b'真的很费时间
我已经尝试使用 pd.read_hdf,它不会增加前缀 'b'。
%time df2=pd.read_hdf(data_trading)
Wall time: 14.7 s
到目前为止哪个更快。
使用 和矢量化 str.decode
,我可以将转换时间缩短到 9.1 秒(因此总时间少于 11 秒):
for key in ['Date', 'Code']:
df[key] = df[key].str.decode("utf-8")
问题:在读取 HDF 5 数据时,是否有更有效的方法将我的字节列转换为字符串 table?
性能的最佳解决方案是停止尝试 "remove the b
prefix." b
前缀是存在的,因为您的数据由字节组成,并且 Python 3 坚持显示此前缀以指示字节在很多地方。即使是没有意义的地方,例如内置 csv
模块的输出。
但在您自己的程序中,这可能不会造成任何伤害,事实上,如果您想要最高性能,最好将这些列保留为 bytes
。如果您使用的是 Python 3.0 到 3.2,则尤其如此,它们始终使用多字节 unicode 表示形式 (see)。
即使您使用的是 Python 3.3 或更高版本,从字节到 unicode 的转换不会花费您任何额外费用 space,如果您有很多数据。
最后,如果您要处理的列大多是独特的字符串且宽度有些一致,则 Pandas 不是最佳选择。例如,如果您有几列文本数据,它们是车牌号,所有这些数据都将适合大约 9 个字符。效率低下是因为 Pandas 并不完全具有字符串列类型,而是使用 object
column type,它包含指向单独存储的字符串的指针。这对 CPU 缓存不利,对内存带宽不利,对内存消耗不利(同样,如果您的字符串大多是唯一的且长度相似)。如果您的字符串具有高度可变的宽度,这可能是值得的,因为一个短字符串只需要它自己的长度加上一个指针,而 NumPy 和 HDF5 中典型的固定宽度存储需要每个字符串的完整列宽(即使是空字符串) .
要在 Python 中获得快速、固定宽度的字符串列,您可以考虑使用 NumPy,您可以通过出色的 h5py
库阅读它。这将为您提供一个 NumPy 数组,它与存储在 HDF5 中的底层数据更加相似。它可能仍然有 b
前缀,因为 Python 坚持非 unicode 字符串总是显示这个前缀,但这不一定是你应该尝试阻止的事情。
目前h5文件中的数据没有前缀'b'。我用下面的代码读取了 h5 文件。我想知道是否有更好的方法来阅读 h5 并且没有前缀 'b'.
import tables as tb
import pandas as pd
import numpy as np
import time
time0=time.time()
pth='d:/download/'
# read data
data_trading=pth+'Trading_v01.h5'
filem=tb.open_file(data_trading,mode='a',driver="H5FD_CORE")
tb_trading=filem.get_node(where='/', name='wind_data')
df=pd.DataFrame.from_records(tb_trading[:])
time1=time.time()
print('\ntime on reading data %6.3fs' %(time1-time0))
# in python3, remove prefix 'b'
df.loc[:,'Date']=[[dt.decode('utf-8')] for dt in df.loc[:,'Date']]
df.loc[:,'Code']=[[cd.decode('utf-8')] for cd in df.loc[:,'Code']]
time2=time.time()
print("\ntime on removing prefix 'b' %6.3fs" %(time2-time1))
print('\ntotal time %6.3fs' %(time2-time0))
时间的结果
time on reading data 1.569s
time on removing prefix 'b' 29.921s
total time 31.490s
你看,去掉前缀'b'真的很费时间
我已经尝试使用 pd.read_hdf,它不会增加前缀 'b'。
%time df2=pd.read_hdf(data_trading)
Wall time: 14.7 s
到目前为止哪个更快。
使用 str.decode
,我可以将转换时间缩短到 9.1 秒(因此总时间少于 11 秒):
for key in ['Date', 'Code']:
df[key] = df[key].str.decode("utf-8")
问题:在读取 HDF 5 数据时,是否有更有效的方法将我的字节列转换为字符串 table?
性能的最佳解决方案是停止尝试 "remove the b
prefix." b
前缀是存在的,因为您的数据由字节组成,并且 Python 3 坚持显示此前缀以指示字节在很多地方。即使是没有意义的地方,例如内置 csv
模块的输出。
但在您自己的程序中,这可能不会造成任何伤害,事实上,如果您想要最高性能,最好将这些列保留为 bytes
。如果您使用的是 Python 3.0 到 3.2,则尤其如此,它们始终使用多字节 unicode 表示形式 (see)。
即使您使用的是 Python 3.3 或更高版本,从字节到 unicode 的转换不会花费您任何额外费用 space,如果您有很多数据。
最后,如果您要处理的列大多是独特的字符串且宽度有些一致,则 Pandas 不是最佳选择。例如,如果您有几列文本数据,它们是车牌号,所有这些数据都将适合大约 9 个字符。效率低下是因为 Pandas 并不完全具有字符串列类型,而是使用 object
column type,它包含指向单独存储的字符串的指针。这对 CPU 缓存不利,对内存带宽不利,对内存消耗不利(同样,如果您的字符串大多是唯一的且长度相似)。如果您的字符串具有高度可变的宽度,这可能是值得的,因为一个短字符串只需要它自己的长度加上一个指针,而 NumPy 和 HDF5 中典型的固定宽度存储需要每个字符串的完整列宽(即使是空字符串) .
要在 Python 中获得快速、固定宽度的字符串列,您可以考虑使用 NumPy,您可以通过出色的 h5py
库阅读它。这将为您提供一个 NumPy 数组,它与存储在 HDF5 中的底层数据更加相似。它可能仍然有 b
前缀,因为 Python 坚持非 unicode 字符串总是显示这个前缀,但这不一定是你应该尝试阻止的事情。