Konwertuj duży plik csv na hdf5

Mam plik csv linii 100m (właściwie wiele oddzielnych plików csv) o łącznej pojemności 84GB. Muszę przekonwertować go do pliku HDF5 z pojedynczym zestawem danych float. Używałem h5py w testach bez żadnych problemów, ale teraz nie mogę zrobić ostatecznego zestawu danych bez wyczerpania pamięci.

Jak mogę pisać do HDF5 bez konieczności przechowywania całego zbioru danych w pamięci? Spodziewam się tutaj prawdziwego kodu, ponieważ powinien być dość prosty.

Właśnie patrzyłem na pytables , ale to nie wygląda na to, że Klasa array (która odpowiada zestawowi danych HDF5) może być zapisywana iteracyjnie. Podobnie, pandy mają metody read_csv i to_hdf w swoim io_tools, ale nie mogę załadować całego zbioru danych na raz, więc to nie zadziała. Być może możesz pomóc mi rozwiązać problem poprawnie z innymi narzędziami w pytables lub pandy.

Author: jmilloy, 2014-11-29

2 answers

Użycie append=True w wywołaniu do 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

Zauważ, że musisz użyć format='table' w pierwszym wywołaniu df.to_hdf, aby uczynić tabelę przydatną. W przeciwnym razie domyślnie formatem jest 'fixed', który jest szybszy do odczytu i zapisu, ale tworzy tabelę, do której nie można dołączyć.

W ten sposób możesz przetwarzać każdy plik CSV po jednym na raz, użyj append=True do zbudowania pliku hdf5. Następnie zastąp ramkę danych lub użyj del df, aby pozwolić, aby stara ramka była śmieciem zebrane.


Alternatywnie, zamiast wywoływać df.to_hdf, możesz dołączyć do 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
 30
Author: unutbu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-29 15:12:36

Powinno to być możliwe z PyTables. Musisz jednak użyć klasy EArray .

Jako przykład, poniżej znajduje się skrypt, który napisałem, aby zaimportować dane treningowe przechowywane w plikach .npy do jednego pliku .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)))

Spójrz na dokumenty, aby uzyskać szczegółowe instrukcje, ale bardzo krótko, Funkcja create_earray zajmuje 1) główny węzeł danych lub węzeł nadrzędny; 2) nazwę tablicy; 3) atom typu danych; 4) kształt z 0 w wymiarze, który chcesz rozwinąć; 5) szczegółowy deskryptor; 6) filtr kompresji ; oraz 7) oczekiwana liczba wierszy wzdłuż rozszerzalnego wymiaru. Wymagane są tylko dwa pierwsze, ale prawdopodobnie wykorzystasz wszystkie siedem w praktyce. Funkcja akceptuje również kilka innych opcjonalnych argumentów; więcej szczegółów można znaleźć w dokumentach.

Po utworzeniu tablicy można użyć jej metody append w oczekiwany sposób.

 6
Author: senderle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-01 14:10:38