将.dat文件转.h5时遇字符串类型兼容问题求助
带字符串列的.dat文件存入HDF5的解决方案
问题背景
需要将包含149列的.dat文件存入HDF5,其中第2、3列为字符串类型,其余为数值类型。使用numpy+h5py和pandas直接存储时均遇到报错,或数据存储异常。
问题原因分析
- numpy+h5py报错
TypeError: No conversion path for dtype: dtype('<U'):h5py不支持numpy默认的Unicode字符串dtype(<U),需要使用固定长度的字节字符串类型(如S20)定义字段类型。 - pandas直接用h5py存储报错
TypeError: Object dtype dtype('O') has no native HDF5 equivalent:pandas读取混合类型数据时,字符串列会被识别为objectdtype,而h5py没有对应的原生HDF5类型。 df.to_hdf数据混乱:未正确设置存储格式和参数,导致字符串列存储异常。
解决方案
方案1:修正numpy+h5py的实现
将字符串列的dtype指定为固定长度的字节字符串,示例代码如下:
import numpy as np import h5py filename = 'VAL220408-invparms.dat' datasetname = 'EM27_104_COCCON_VAL/220408' # 定义dtype:第2、3列为长度20的字节字符串,其余为float dtvec = [('col{}'.format(i), float) for i in range(149)] dtvec[1] = ('col1', 'S20') # 索引从0开始,第2列对应索引1 dtvec[2] = ('col2', 'S20') # 第3列对应索引2 dataset = np.genfromtxt(filename, skip_header=0, names=True, dtype=dtvec) with h5py.File('my_data.h5', 'w') as fh5: fh5.create_dataset(datasetname, data=dataset)
注意:
S20表示长度为20的字节字符串,可根据实际字符串长度调整数值;读取后转回Unicode字符串可用.decode('utf-8')处理。
方案2:使用pandas的HDFStore正确存储
先指定dtypes读取数据,再用HDFStore以表格格式存储,确保字符串列正确保存:
import pandas as pd filename = 'VAL220408-invparms.dat' datasetname = 'EM27_104_COCCON_VAL/220408' # 构造dtype字典:第2、3列设为str,其余为float col_names = pd.read_csv(filename, nrows=0, sep="\s+").columns dtype_dict = {col: str if idx in [1,2] else float for idx, col in enumerate(col_names)} df = pd.read_csv(filename, header=0, sep="\s+", dtype=dtype_dict) # 使用HDFStore存储,格式为table支持后续查询 with pd.HDFStore('my_data.h5', mode='w') as store: store.put(datasetname, df, format='table', data_columns=True)
若已知表头列名,可直接指定
dtype_dict(如dtype_dict = {'time_col': str, 'id_col': str, ...}),避免自动推断错误。
方案3:用h5py分数据集存储(灵活控制类型)
如果需要更精细的控制,可将数值列和字符串列分别存入HDF5的不同数据集:
import pandas as pd import h5py filename = 'VAL220408-invparms.dat' groupname = 'EM27_104_COCCON_VAL' dataset_num_name = '220408_numeric' dataset_str_name = '220408_strings' df = pd.read_csv(filename, header=0, sep="\s+") # 分离数值列和字符串列 num_cols = df.columns.drop(df.columns[[1,2]]) str_cols = df.columns[[1,2]] with h5py.File('my_data.h5', 'w') as fh5: # 创建组 group = fh5.create_group(groupname) # 存储数值列 group.create_dataset(dataset_num_name, data=df[num_cols].values) # 存储字符串列:转为字节数组 str_data = df[str_cols].apply(lambda x: x.str.encode('utf-8')).values group.create_dataset(dataset_str_name, data=str_data)
验证方法
可以用h5py或pandas读取HDF5文件验证:
# 用h5py读取 with h5py.File('my_data.h5', 'r') as fh5: data = fh5['EM27_104_COCCON_VAL/220408'][:] # 字符串列转Unicode str_col1 = data['col1'].decode('utf-8') # 用pandas读取 df_read = pd.read_hdf('my_data.h5', key='EM27_104_COCCON_VAL/220408') print(df_read.dtypes)
内容的提问来源于stack exchange,提问作者Ozzluis Hernandez
相关产品推荐
相关产品推荐

