Conversion gros csv en hdf5

j'ai un fichier csv ligne 100M (en fait beaucoup de fichiers csv séparés) totalisant 84 GO. J'ai besoin de le convertir en un fichier HDF5 avec un ensemble de données float unique. J'ai utilisé h5py dans testing sans aucun problème, mais maintenant je ne peux pas faire l'ensemble de données final sans manquer de mémoire.

Comment puis-je écrire à HDF5 sans avoir à stocker l'ensemble des données en mémoire? J'attends un vrai code ici, parce que ça devrait être assez simple.

je suis juste à la recherche pytables, mais il ne semble pas que la classe array (qui correspond à un ensemble de données HDF5) puisse être écrite de façon itérative. De même, pandas a read_csv et to_hdf méthodes dans sa io_tools, mais je ne peux pas charger l'ensemble de données en une seule fois donc ça ne marchera pas. Peut-être Pouvez-vous m'aider à résoudre le problème correctement avec d'autres outils dans pytables ou pandas.

22
demandé sur jmilloy 2014-11-29 17:08:35

2 réponses

Utiliser append=True dans l'appel à 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'))

les rendements

    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

Notez que vous devez utiliser format='table' dans le premier appel à df.to_hdf pour rendre la table annexe. Sinon, le format est 'fixed' par défaut, ce qui est plus rapide pour la lecture et l'écriture, mais crée une table qui ne peut pas être ajouté.

Ainsi, vous pouvez traiter chaque CSV un à la fois, utilisez append=True pour construire le hdf5 fichier. Puis écraser la DataFrame ou utilisez del df pour permettre à l'ancienne base de données d'être ramassée.


alternativement, au lieu d'appeler df.to_hdf, vous pouvez Ajouter à une 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()

les rendements

    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
répondu unutbu 2014-11-29 15:12:36

cela devrait être possible avec PyTables. Vous aurez besoin d'utiliser le EArray classe.

à titre d'exemple, voici un script que j'ai écrit pour importer des données d'entraînement stockées sous .npy les fichiers en un seul .h5 fichier.

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)))

jetez un coup d'oeil aux docs pour des instructions détaillées, mais très brièvement, le create_earray la fonction prend 1) une racine de données ou un noeud parent; 2) un nom de tableau; 3) un atome de type de données; 4) une forme avec un 0 dans la dimension vous souhaitez développer; 5) une verbose descripteur; 6) un filtre de compression; et 7) un nombre prévu de lignes le long de la dimension extensible. Seuls les deux premiers sont nécessaires, mais vous utiliserez probablement les sept en pratique. La fonction accepte quelques autres arguments optionnels aussi bien; encore une fois, voir les docs pour plus de détails.

une fois le tableau créé, vous pouvez utiliser son append méthode de la manière prévue.

6
répondu senderle 2014-12-01 14:10:38