#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"
. Это перезаписывает предыдущий файл, в результате чего происходит автоматическая «перепаковка». Затем я записываю другие ключи.
В моем случае фреймы данных не слишком велики, поэтому возможна одноразовая загрузка всех фреймов данных в память. Полученный размер файла теперь точно соответствует тому, каким он должен быть.