4

我有一个非常大的数据集,我通过 append 分块写入 hdf5,如下所示:

with pd.HDFStore(self.train_store_path) as train_store:
    for filepath in tqdm(filepaths):
        with open(filepath, 'rb') as file:
            frame = pickle.load(file)

        if frame.empty:
            os.remove(filepath)
            continue

        try:
            train_store.append(
                key='dataset', value=frame,
                min_itemsize=itemsize_dict)
            os.remove(filepath)
        except KeyError as e:
            print(e)
        except ValueError as e:
            print(frame)
            print(e)
        except Exception as e:
            print(e) 

数据太大而无法加载到一个 DataFrame 中,所以我想尝试 vaex 进行进一步处理。不过有几件事我真的不明白。

由于 vaex 在 hdf5 中使用的表示形式与 pandas/pytables (VOTable) 不同,我想知道如何在这两种格式之间进行转换。我尝试将数据分块加载到 pandas 中,将其转换为 vaex DataFrame 然后存储它,但似乎无法将数据附加到现有的 vaex hdf5 文件中,至少我找不到。

真的没有办法从 vaex 中创建大型 hdf5 数据集吗?是将现有数据集转换为 vaex 表示的唯一选择(通过 python 脚本或 TOPCAT 构建文件)?

与我之前的问题相关,如果我在核心外使用 vaex 中的大型数据集,是否可以将我在 vaex 中应用的任何转换的结果保存到 hdf5 文件中?

4

1 回答 1

7

这种存储格式的问题在于它不是基于列的,它不能很好地处理具有大量行的数据集,因为例如,如果您只使用 1 列,操作系统可能还会读取大部分其他列以及 CPU 缓存都会被它污染。最好将它们存储为基于列的格式,例如 vaex 的 hdf5 格式或箭头。

转换为 vaex 数据框可以使用:

import vaex
vaex_df = vaex.from_pandas(pandas_df, copy_index=False)

您可以对每个数据帧执行此操作,并将它们作为 hdf5 或箭头存储在磁盘上:

vaex_df.export('batch_1.hdf5')  # or 'batch_1.arrow'

如果对许多文件执行此操作,则可以延迟(即不会制作内存副本)连接它们,或使用 vaex.open 函数:

df1 = vaex.open('batch_1.hdf5')
df2 = vaex.open('batch_2.hdf5')
df = vaex.concat([df1, df2]) # will be seen as 1 dataframe without mem copy
df_altnerative = vaex.open('batch*.hdf5')  # same effect, but only needs 1 line

关于您关于转换的问题:

如果您对数据框进行转换,您可以写出计算值,或获取包含转换的“状态”:

import vaex
df = vaex.example()
df['difference'] = df.x - df.y
# df.export('materialized.hdf5', column_names=['difference'])  # do this if IO is fast, and memory abundant
# state = df.state_get()  # get state in memory
df.state_write('mystate.json') # or write as json


import vaex
df = vaex.example()
# df.join(vaex.open('materialized.hdf5'))  # join on rows number (super fast, 0 memory use!)
# df.state_set(state)  # or apply the state from memory
df.state_load('mystate.json')  # or from disk
df
于 2019-12-11T08:50:56.747 回答