Подтвердить что ты не робот

Преобразование больших csv в hdf5

У меня есть CSV файл 100M (на самом деле много отдельных файлов csv) на 84GB. Мне нужно преобразовать его в файл HDF5 с одним набором данных с плавающей точкой. Я использовал h5py при тестировании без каких-либо проблем, но теперь я не могу сделать окончательный набор данных без нехватки памяти.

Как я могу записать на HDF5 без необходимости хранить весь набор данных в памяти? Я ожидаю действительный код здесь, потому что это должно быть довольно просто.

Я просто смотрел в pytables, но это не похоже на то, что класс массива (который соответствует набору данных HDF5) можно записать итеративно. Аналогично, pandas имеет методы read_csv и to_hdf в своем io_tools, но я не могу загрузить весь набор данных за один раз, так что это не сработает. Возможно, вы можете помочь мне правильно решить проблему с помощью других инструментов в pytables или pandas.

4b9b3361

Ответ 1

Используйте append=True при вызове to_hdf:

import numpy as np
import pandas as pd

filename = '/tmp/test.h5'

df = pd.DataFrame(np.arange(10).reshape((5,2)), columns=['A', 'B'])
print(df)
#    A  B
# 0  0  1
# 1  2  3
# 2  4  5
# 3  6  7
# 4  8  9

# Save to HDF5
df.to_hdf(filename, 'data', mode='w', format='table')
del df    # allow df to be garbage collected

# Append more data
df2 = pd.DataFrame(np.arange(10).reshape((5,2))*10, columns=['A', 'B'])
df2.to_hdf(filename, 'data', append=True)

print(pd.read_hdf(filename, 'data'))

дает

    A   B
0   0   1
1   2   3
2   4   5
3   6   7
4   8   9
0   0  10
1  20  30
2  40  50
3  60  70
4  80  90

Обратите внимание, что вам нужно использовать format='table' при первом вызове df.to_hdf, чтобы сделать таблицу доступной. В противном случае формат 'fixed' по умолчанию, который быстрее для чтения и записи, но создает таблицу, к которой нельзя добавить.

Таким образом, вы можете обрабатывать каждый CSV один за раз, используйте append=True для создания файла hdf5. Затем перезапишите DataFrame или используйте del df, чтобы старый мусор был собран.


В качестве альтернативы вместо вызова df.to_hdf вы можете добавить в HDFStore:

import numpy as np
import pandas as pd

filename = '/tmp/test.h5'
store = pd.HDFStore(filename)

for i in range(2):
    df = pd.DataFrame(np.arange(10).reshape((5,2)) * 10**i, columns=['A', 'B'])
    store.append('data', df)

store.close()

store = pd.HDFStore(filename)
data = store['data']
print(data)
store.close()

дает

    A   B
0   0   1
1   2   3
2   4   5
3   6   7
4   8   9
0   0  10
1  20  30
2  40  50
3  60  70
4  80  90

Ответ 2

Это должно быть возможно с помощью PyTables. Вам нужно будет использовать класс EArray.

В качестве примера приведено следующее: script Я написал для импортирования данных с каналами обучения, хранящихся в виде файлов .npy, в один файл .h5.

import numpy
import tables
import os

training_data = tables.open_file('nn_training.h5', mode='w')
a = tables.Float64Atom()
bl_filter = tables.Filters(5, 'blosc')   # fast compressor at a moderate setting

training_input =  training_data.create_earray(training_data.root, 'X', a,
                                             (0, 1323), 'Training Input',
                                             bl_filter, 4000000)
training_output = training_data.create_earray(training_data.root, 'Y', a,
                                             (0, 27), 'Training Output',
                                             bl_filter, 4000000)

for filename in os.listdir('input'):
    print "loading {}...".format(filename)
    a = numpy.load(os.path.join('input', filename))
    print "writing to h5"
    training_input.append(a)

for filename in os.listdir('output'):
    print "loading {}...".format(filename)
    training_output.append(numpy.load(os.path.join('output', filename)))

Взгляните на документы для подробных инструкций, но очень кратко, функция create_earray принимает 1) корень данных или родительский node; 2) имя массива; 3) атом типа данных; 4) форма с 0 в размерности, которую вы хотите расширить; 5) подробный дескриптор; 6) a фильтр сжатия; и 7) ожидаемое количество строк вдоль расширяемого размера. Требуются только первые два, но вы, вероятно, будете использовать все семь на практике. Функция принимает и другие необязательные аргументы; еще раз, см. документы для деталей.

Как только массив будет создан, вы можете использовать его метод append ожидаемым образом.