Le logiciel statistique Stata permet d'enregistrer de courts extraits de texte dans un ensemble de données. Pour ce faire, utilisez notes
et/ou characteristics
.
C'est une fonctionnalité très utile pour moi car elle me permet d'enregistrer une variété d'informations, allant des rappels et des listes de tâches aux informations sur la façon dont j'ai généré les données, ou même quelle était la méthode d'estimation pour une variable particulière.
J'essaie maintenant de proposer une fonctionnalité similaire dans Python 3.6. Jusqu'à présent, j'ai regardé en ligne et consulté un certain nombre de messages, qui ne traitent cependant pas exactement de ce que je veux faire.
Quelques publications de référence:
meilleur moyen de conserver les tableaux numpy sur le disque
Quelle est la différence entre enregistrer un pandas dataframe à pickle et à csv?
Comment afficher le contenu d'un objet de données dans un fichier npz?
Pour un petit tableau NumPy
, j'ai conclu qu'une combinaison de la fonction numpy.savez()
et un dictionary
peut stocker de manière adéquate toutes les informations pertinentes dans un un seul fichier.
Par exemple:
a = np.array([[2,4],[6,8],[10,12]])
d = {"first": 1, "second": "two", "third": 3}
np.savez(whatever_name.npz, a=a, d=d)
data = np.load(whatever_name.npz)
arr = data['a']
dic = data['d'].tolist()
Cependant, la question demeure:
Existe-t-il de meilleures façons d'incorporer potentiellement d'autres informations dans un fichier contenant un tableau NumPy
ou un (grand) Pandas
DataFrame
?
Je suis particulièrement intéressé à entendre parler des pros et contre des suggestions que vous pourriez avoir avec des exemples. Moins il y a de dépendances, mieux c'est.
Il existe de nombreuses options. Je ne parlerai que du HDF5, car j'ai de l'expérience avec ce format.
Avantages : Portable (peut être lu en dehors de Python), compression native, capacités de mémoire insuffisante, prise en charge des métadonnées.
Inconvénients : dépendance à une seule API C de bas niveau, possibilité de corruption de données en tant que fichier unique, la suppression de données ne réduit pas automatiquement la taille.
D'après mon expérience, pour les performances et la portabilité, à éviterpyTables
/HDFStore
pour stocker des données numériques. Vous pouvez à la place utiliser l'interface intuitive fournie par h5py
.
Stocker un tableau
import h5py, numpy as np
arr = np.random.randint(0, 10, (1000, 1000))
f = h5py.File('file.h5', 'w', libver='latest') # use 'latest' for performance
dset = f.create_dataset('array', shape=(1000, 1000), data=arr, chunks=(100, 100)
compression='gzip', compression_opts=9)
Compression et segmentation
Il existe de nombreux choix de compression, par ex. blosc
et lzf
sont de bons choix pour les performances de compression et de décompression respectivement. Remarque gzip
est natif; les autres filtres de compression peuvent ne pas être livrés par défaut avec votre installation HDF5.
La segmentation est une autre option qui, lorsqu'elle est alignée sur la façon dont vous lisez les données hors mémoire, peut améliorer considérablement les performances.
Ajoutez quelques attributs
dset.attrs['Description'] = 'Some text snippet'
dset.attrs['RowIndexArray'] = np.arange(1000)
Stockez un dictionnaire
for k, v in d.items():
f.create_dataset('dictgroup/'+str(k), data=v)
Accès hors mémoire
dictionary = f['dictgroup']
res = dictionary['my_key']
Rien ne remplace la lecture du h5py
documentation , qui expose la plupart de l'API C, mais vous devriez voir d'après ce qui précède qu'il y a une grande flexibilité.
Je suis d'accord avec JPP que le stockage hdf5 est une bonne option ici. La différence entre sa solution et la mienne est que la mienne utilise Pandas cadres de données au lieu de tableaux numpy. Je préfère le cadre de données car cela permet des types mixtes, une indexation à plusieurs niveaux (même l'indexation datetime, ce qui est TRÈS important pour mon travail) et l'étiquetage des colonnes, ce qui m'aide à me souvenir de la façon dont les différents ensembles de données sont organisés. De plus, Pandas fournit une multitude de fonctionnalités intégrées (un peu comme numpy). Un autre avantage de l'utilisation de Pandas est qu'il a un créateur hdf intégré (c'est-à-dire pandas.DataFrame.to_hdf), que je trouve pratique
Lors du stockage de la trame de données sur h5, vous avez la possibilité de stocker également un dictionnaire de métadonnées, qui peut être vos notes pour vous-même, ou des métadonnées réelles qui n'ont pas besoin d'être stockées dans la trame de données (je l'utilise également pour définir des indicateurs, par exemple {'is_agl': True, 'scale_factor': 100, 'already_corrected': False, etc.}. À cet égard, il n'y a pas de différence entre l'utilisation d'un tableau numpy et d'une trame de données. Pour la solution complète, voir ma question et solution d'origine ici.
Un moyen pratique pourrait être d'incorporer des métadonnées directement dans le tableau Numpy. L'avantage est que, comme vous le souhaitez, il n'y a pas de dépendance supplémentaire et il est très simple à utiliser dans le code. Cependant, cela ne répond pas entièrement à votre question, car vous avez toujours besoin d'un mécanisme pour enregistrer les données, et je recommanderais d'utiliser la solution de jpp utilisant HDF5.
Pour inclure des métadonnées dans un ndarray
, il y a un exemple dans la documentation . Vous devez essentiellement sous-classer un ndarray
et ajouter un champ info
ou metadata
ou autre.
Cela donnerait (code du lien ci-dessus)
import numpy as np
class ArrayWithInfo(np.ndarray):
def __new__(cls, input_array, info=None):
# Input array is an already formed ndarray instance
# We first cast to be our class type
obj = np.asarray(input_array).view(cls)
# add the new attribute to the created instance
obj.info = info
# Finally, we must return the newly created object:
return obj
def __array_finalize__(self, obj):
# see InfoArray.__array_finalize__ for comments
if obj is None: return
self.info = getattr(obj, 'info', None)
Pour enregistrer les données via numpy
, vous devez surcharger la fonction write
ou utiliser une autre solution.
la réponse de jpp est assez complète, je voulais juste mentionner qu'à partir de pandas v22 est une option très pratique et rapide avec presque aucun inconvénient vs csv (acceptez peut-être la pause-café).
Au moment de la rédaction, vous devrez également
pip install pyarrow
En termes d'ajout d'informations, vous disposez des métadonnées qui sont attachées aux données
import pyarrow as pa
import pyarrow.parquet as pq
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.normal(size=(1000, 10)))
tab = pa.Table.from_pandas(df)
tab = tab.replace_schema_metadata({'here' : 'it is'})
pq.write_table(tab, 'where_is_it.parq')
pq.read_table('where_is_it.parq')
Pyarrow table
0: double
1: double
2: double
3: double
4: double
5: double
6: double
7: double
8: double
9: double
__index_level_0__: int64
metadata
--------
{b'here': b'it is'}
Pour remettre cela aux pandas:
tab.to_pandas()