【问题标题】:How to define an individual data type for each HDF5 column with h5py如何使用 h5py 为每个 HDF5 列定义单独的数据类型
【发布时间】:2020-03-10 04:47:47
【问题描述】:

我检查了不同的解决方案,但不明白如何将它们应用于多维数组。准确地说,我的代码生成的数组比它应该的要大,如下图所示:

import h5py
import pandas as pd
import numpy as np

data = [[1583663558450195, -7.063664436340332, -6.2776079177856445, -4.206898212432861, -4.206898212432861], [1583663558450195, -7.063664436340332, -6.2776079177856445, -4.206898212432861, -4.206898212432861], [1583663558450195, -7.063664436340332, -6.2776079177856445, -4.206898212432861, -4.206898212432861], [1583663558450195, -7.063664436340332, -6.2776079177856445, -4.206898212432861, -4.206898212432861], [1583663558450195, -7.063664436340332, -6.2776079177856445, -4.206898212432861, -4.206898212432861], [1583663558450195, -7.063664436340332, -6.2776079177856445, -4.206898212432861, -4.206898212432861], [1583663558450195, -7.063664436340332, -6.2776079177856445, -4.206898212432861, -4.206898212432861], [1583663558450195, -7.063664436340332, -6.2776079177856445, -4.206898212432861, -4.206898212432861], [1583663558450195, -7.063664436340332, -6.2776079177856445, -4.206898212432861, -4.206898212432861], [1583663558450195, -7.063664436340332, -6.2776079177856445, -4.206898212432861, -4.206898212432861]]

df = pd.DataFrame(data)

hf = h5py.File('dtype.h5', 'w')

dataTypes = np.dtype([('ts', 'u8'), ('x', 'f4'), ('y', 'f4'), ('z', 'f4'), ('temp', 'f4')])
ds = hf.create_dataset('Acceleration', data=df.astype(dataTypes))

我想做成这样,列分别是 uint64, 4x float32:

                 ts         x         y         z      temp
0  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
1  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
2  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
3  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
4  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
5  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
6  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
7  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
8  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
9  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898

【问题讨论】:

    标签: python hdf5 h5py


    【解决方案1】:

    你的df

    In [370]: df                                                                                   
    Out[370]: 
                      0         1         2         3         4
    0  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
    1  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
    2  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
    3  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
    ...
    

    df.astype(dataTypes) 给了我一个TypeError(我的pd 不是最新的)。

    In [373]: df.to_records()                                                                      
    Out[373]: 
    rec.array([(0, 1583663558450195, -7.06366444, -6.27760792, -4.20689821, -4.20689821),
               (1, 1583663558450195, -7.06366444, -6.27760792, -4.20689821, -4.20689821),
               (2, 1583663558450195, -7.06366444, -6.27760792, -4.20689821, -4.20689821),
               (3, 1583663558450195, -7.06366444, -6.27760792, -4.20689821, -4.20689821),
               (4, 1583663558450195, -7.06366444, -6.27760792, -4.20689821, -4.20689821),
               (5, 1583663558450195, -7.06366444, -6.27760792, -4.20689821, -4.20689821),
               (6, 1583663558450195, -7.06366444, -6.27760792, -4.20689821, -4.20689821),
               (7, 1583663558450195, -7.06366444, -6.27760792, -4.20689821, -4.20689821),
               (8, 1583663558450195, -7.06366444, -6.27760792, -4.20689821, -4.20689821),
               (9, 1583663558450195, -7.06366444, -6.27760792, -4.20689821, -4.20689821)],
              dtype=[('index', '<i8'), ('0', '<i8'), ('1', '<f8'), ('2', '<f8'), ('3', '<f8'), ('4', '<f8')])
    

    这个数组应该用h5py保存。

    to_records 的参数可能会创建更接近您的dataTypes 的东西。我会让你探索这些。

    但是通过recfunctions 的最新重组,我们可以使用以下方式制作结构化数组:

    In [385]: import numpy.lib.recfunctions as rf                                                  
    In [386]: rf.unstructured_to_structured(np.array(data), dataTypes)                             
    Out[386]: 
    array([(1583663558450195, -7.0636644, -6.277608, -4.206898, -4.206898),
           (1583663558450195, -7.0636644, -6.277608, -4.206898, -4.206898),
           (1583663558450195, -7.0636644, -6.277608, -4.206898, -4.206898),
           (1583663558450195, -7.0636644, -6.277608, -4.206898, -4.206898),
           (1583663558450195, -7.0636644, -6.277608, -4.206898, -4.206898),
           (1583663558450195, -7.0636644, -6.277608, -4.206898, -4.206898),
           (1583663558450195, -7.0636644, -6.277608, -4.206898, -4.206898),
           (1583663558450195, -7.0636644, -6.277608, -4.206898, -4.206898),
           (1583663558450195, -7.0636644, -6.277608, -4.206898, -4.206898),
           (1583663558450195, -7.0636644, -6.277608, -4.206898, -4.206898)],
          dtype=[('ts', '<u8'), ('x', '<f4'), ('y', '<f4'), ('z', '<f4'), ('temp', '<f4')])
    

    np.array(data) 是 (10,5) 浮点数组。

    In [388]: pd.DataFrame(_386)                                                                   
    Out[388]: 
                     ts         x         y         z      temp
    0  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
    1  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
    2  1583663558450195 -7.063664 -6.277608 -4.206898 -4.206898
     ...
    

    【讨论】:

    • 你检查过df.astype(dataTypes)吗?你的图片看起来很像np.array(data, dtype=dataTypes)。结构化数组的 data 应该是元组列表,而不是列表列表,如 np.array([tuple(i) for i in data], dtype=dataTypes)
    【解决方案2】:

    这个问题比最初出现的要复杂。最初,我认为我可以应用与我对您之前的问题SO 60562311:define individual datatypes for each column 的回答相同的方法。但是,它有一些细微的差别:

    1. 此数据是 List 列表 VS 5x5 NumPy 数组
    2. 此数据是混合类型(整数和浮点数)VS 所有浮点数
    3. 这个数据比前面的例子有更多的有效数字

    这如何改变程序?

    • 列表列表可以转换为 NumPy 数组 np.array(data) 但是,这并不能完全解决问题。您仍然会得到重复的列。
    • 您还需要在 dtype 声明中更改对象类型。 f4需要是f8u8需要是uint16

    进行这些更改,一切都会像我之前的回答一样工作。请参阅下面对原始代码的更新。

    dataTypes = np.dtype([('ts', 'uint16'), ('x', 'f8'), 
                ('y', 'f8'), ('z', 'f8'), ('temp', 'f8')])
    # create array from list of lists
    d_arr = np.array(data) 
    # create record array
    rec_arr = np.rec.array(d_arr, dtype=dataTypes)
    with h5py.File('dtype.h5', 'w') as hf:
        ds = hf.create_dataset('Acceleration', data=rec_arr)
    

    【讨论】:

    • 从昨天开始我就一直在摸不着头脑,为什么在分配列名后,所有列都出现在单个列 0 下。您是否还告诉我为什么 f4 必须是 f8
    • 好问题。花了一段时间才弄清楚这一点,我不完全确定。 :-) 我怀疑这与数据中有效数字的数量以及创建记录数组时将float64 转换为无符号整数有关。在我的代码中,它以 np.array(data) 调用开始。 d_arr 的结果 dtype 为 float64 如果将列表转换为 float32(f4),则会丢失一半有效数字。此外,将float64 转换为u8 会导致有关“更改为更大的dtype”的警告。我怀疑这就是触发多列的原因。
    • 再想一想:rf.unstructured_to_structured()' from recfunctions` 似乎可以干净地处理这个问题。这对我来说是新的,所以我需要调查。
    猜你喜欢
    • 2016-03-29
    • 2016-04-04
    • 2020-06-12
    • 2019-12-19
    • 2015-10-29
    • 2016-03-23
    • 2018-04-14
    • 2016-02-27
    • 2021-05-14
    相关资源
    最近更新 更多