HDF5 prendre plus D'espace que CSV?

Prenons l'exemple suivant:

Préparer les données:

import string
import random
import pandas as pd

matrix = np.random.random((100, 3000))
my_cols = [random.choice(string.ascii_uppercase) for x in range(matrix.shape[1])]
mydf = pd.DataFrame(matrix, columns=my_cols)
mydf['something'] = 'hello_world'

Définissez la compression la plus élevée possible pour HDF5:

store = pd.HDFStore('myfile.h5',complevel=9, complib='bzip2')
store['mydf'] = mydf
store.close()

Enregistrer aussi au format CSV:

mydf.to_csv('myfile.csv', sep=':')

Le résultat est:

  • {[3] } est 5.6 MB grand
  • myfile.h5 est 11 MB grand

La différence augmente à mesure que les jeux de données s'agrandissent.

J'ai essayé avec d'autres méthodes et niveaux de compression. Est-ce un bug? (J'utilise Pandas 0.11 et la dernière version stable de HDF5 et Python).

26
demandé sur Amelio Vazquez-Reina 2013-05-20 01:57:11

1 réponses

Copie de ma réponse du problème: https://github.com/pydata/pandas/issues/3651

Votre échantillon est vraiment trop petit. HDF5 a une bonne quantité de frais généraux avec de très petites tailles (même les entrées 300k sont sur le côté le plus petit). Ce qui suit est sans compression de chaque côté. Les flotteurs sont vraiment plus efficacement représentés en binaire (comme une représentation de texte).

De plus, HDF5 est basé sur des lignes. Vous obtenez beaucoup d'efficacité en ayant des tables qui ne sont pas trop larges mais sont assez longues. (D'où votre exemple n'est pas très efficace en HDF5 du tout, stockez-le transposé dans ce cas)

J'ai régulièrement des tables qui sont 10M + lignes et les temps de requête peuvent être dans la ms. même l'exemple ci-dessous est petit. Avoir des fichiers 10+GB est assez commun (sans parler des gars de l'astronomie qui 10GB + est à quelques secondes!)

-rw-rw-r--  1 jreback users 203200986 May 19 20:58 test.csv
-rw-rw-r--  1 jreback users  88007312 May 19 20:59 test.h5

In [1]: df = DataFrame(randn(1000000,10))

In [9]: df
Out[9]: 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1000000 entries, 0 to 999999
Data columns (total 10 columns):
0    1000000  non-null values
1    1000000  non-null values
2    1000000  non-null values
3    1000000  non-null values
4    1000000  non-null values
5    1000000  non-null values
6    1000000  non-null values
7    1000000  non-null values
8    1000000  non-null values
9    1000000  non-null values
dtypes: float64(10)

In [5]: %timeit df.to_csv('test.csv',mode='w')
1 loops, best of 3: 12.7 s per loop

In [6]: %timeit df.to_hdf('test.h5','df',mode='w')
1 loops, best of 3: 825 ms per loop

In [7]: %timeit pd.read_csv('test.csv',index_col=0)
1 loops, best of 3: 2.35 s per loop

In [8]: %timeit pd.read_hdf('test.h5','df')
10 loops, best of 3: 38 ms per loop

Je ne m'inquiéterais vraiment pas de la taille (je soupçonne que vous ne l'êtes pas, mais que vous êtes simplement intéressé, ce qui est bien). Le point de HDF5 est que le disque est bon marché, cpu est bon marché, mais vous ne pouvez pas tout avoir en mémoire à la fois, donc nous optimisons en utilisant chunking

34
répondu Jeff 2013-05-20 01:37:27