Замена групп в файле h5py продолжает увеличивать размер

#python-3.x #pandas #dataframe #h5py

Вопрос:

У меня есть несколько кадров данных, которые мне нужно сохранить в файле HDF5, как по отдельности, так и в совокупности. Я пытаюсь использовать группы для сохранения отдельных кадров данных. Кадры данных сохраняются с помощью:

 df1.to_hdf(filename, key="S1", mode="a", complevel=9)
df2.to_hdf(filename, key="S2", mode="a", complevel=9)
...
 

а затем объединенный кадр данных сохраняется в виде:

 df_concatenated = pd.concat([df1, df2])
df_concatenated.to_hdf(filename, key="key", mode="a", complevel=9)
 

Функциональность работает, и повторная загрузка кадров данных подтверждает, что как отдельные, так и объединенные кадры данных сохранены правильно. Однако размер файла продолжает расти каждый раз, когда я запускаю to_hdf . Ключи в файле остаются неизменными после каждой записи, хотя:

 import h5py
f = h5py.File(filename, mode='r')
f.keys()
 

показывает ["S1", "S2", "key"] , как и ожидалось.

Я думал, что проблема вызвана некоторыми зависшими данными, поэтому я добавил код для удаления ранее существующих данных, если это применимо:

 try:
    with h5py.File(filename, mode='a') as f:
        del f[key]
except (KeyError, TypeError, FileNotFoundError):
    pass
 

Но размер файла продолжает расти, почти удваиваясь каждый раз, когда я перезаписываю часть файла (один ключ и составной «ключ»).

Как я могу сохранить размер файла постоянным для одних и тех же данных? То есть, если я использую to_hdf для перезаписи данных идентичный фрейм данных, как я могу гарантировать, что размер файла останется прежним?

Комментарии:

1. HDF5 не восстанавливает выделенное пространство из удаленных данных. Он будет повторно использовать пространство, если вы добавите данные. Решение состоит в том, чтобы запустить repack утилиту (из группы HDF) или ptrepack доставить ее с пакетом PyTables.

Ответ №1:

Спасибо @kcw78 за ваше объяснение и возможное решение. Я не контролирую среду, в которой может выполняться этот код, поэтому я не могу надежно вызывать утилиты.

Вот решение, которое я использую прямо сейчас. Не идеально, но это работает.

 with h5py.File(filename, mode='r') as f:
    all_keys = list(f.keys())

...

df_dict = {}
for k in all_keys:
    if k != "key":
        df_dict[k] = pd.read_hdf(filename, key=k)

...

# Overwrite file here
df_concatenated.to_hdf(filename, key="key", mode="w", complevel=9)

...
for k, v in df_dict.items():
    v.to_hdf(filename, key=k, mode="a", complevel=9)
 

В основном я просто загружаю все фреймы данных в память и при записи объединенного фрейма данных обратно использую mode="w" . Это перезаписывает предыдущий файл, в результате чего происходит автоматическая «перепаковка». Затем я записываю другие ключи.

В моем случае фреймы данных не слишком велики, поэтому возможна одноразовая загрузка всех фреймов данных в память. Полученный размер файла теперь точно соответствует тому, каким он должен быть.