Enregistrer des attributs supplémentaires dans Pandas Dataframe
je me souviens de mes jours MatLab utilisant des tableaux structurés où vous pourriez stocker des données différentes comme un attribut de la structure principale. Quelque chose comme:
a = {}
a.A = magic(10)
a.B = magic(50); etc.
où A. A et A. B sont complètement séparés les uns des autres vous permettant de stocker différents types au sein de a et d'opérer sur eux comme vous le souhaitez. Les Pandas nous permet de faire quelque chose de similaire, mais pas tout à fait la même.
j'utilise Pandas et je veux stocker les attributs d'un dataframe sans le mettre dans une dataframe. Cela peut être fait via:
import pandas as pd
a = pd.DataFrame(data=pd.np.random.randint(0,100,(10,5)),columns=list('ABCED')
# now store an attribute of <a>
a.local_tz = 'US/Eastern'
maintenant, le fuseau horaire local est stocké dans a, mais je ne peux pas sauvegarder cet attribut quand je sauvegarde la dataframe (i.e. après avoir rechargé a il n'y a pas de A. local_tz). Est-il un moyen de sauver ces attributs?
actuellement, Je ne fais que de nouvelles colonnes dans la base de données pour contenir des informations comme le fuseau horaire, la latitude, le longituded, etc. mais cela semble être un peu à l' déchet. En outre, lorsque je fais une analyse des données, je me heurte à des problèmes de devoir exclure ces autres colonnes.
################## COMMENCER À MODIFIER ##################
grâce aux conseils d'unutbu, je stocke maintenant les données au format h5. Comme nous l'avons mentionné, il est risqué de renvoyer les métadonnées en tant qu'attributs de la base de données. Cependant, comme je suis le créateur de ces fichiers (et des algorithmes de traitement), je peux choisir ce qui est stocké comme métadonnées et ce qui ne l'est pas. Lorsque en traitant les données qui vont aller dans les fichiers h5, je choisis de stocker les métadonnées dans un dictionnaire qui est initialisé comme un attribut de mes classes. J'ai créé une classe IO simple pour importer les données h5, et j'ai fait les métadonnées comme attributs de classe. Maintenant, je peux travailler sur mes images de données sans risque de perdre les métadonnées.
class IO():
def __init__(self):
self.dtfrmt = 'dummy_str'
def h5load(self,filename,update=False):
'''h5load loads the stored HDF5 file. Both the dataframe (actual data) and
the associated metadata are stored in the H5file
NOTE: This does not load "any" H5
file, it loads H5 files specifically created to hold dataframe data and
metadata.
When multi-indexed dataframes are stored in the H5 format the date
values (previously initialized with timezone information) lose their
timezone localization. Therefore, <h5load> re-localizes the 'DATE'
index as UTC.
Parameters
----------
filename : string/path
path and filename of H5 file to be loaded. H5 file must have been
created using <h5store> below.
udatedf : boolean True/False
default: False
If the selected dataframe is to be updated then it is imported
slightly different. If update==True, the <metadata> attribute is
returned as a dictionary and <data> is returned as a dataframe
(i.e., as a stand-alone dictionary with no attributes, and NOT an
instance of the IO() class). Otherwise, if False, <metadata> is
returned as an attribute of the class instance.
Output
------
data : Pandas dataframe with attributes
The dataframe contains only the data as collected by the instrument.
Any metadata (e.g. timezone, scaling factor, basically anything that
is constant throughout the file) is stored as an attribute (e.g. lat
is stored as <data.lat>).'''
with pd.HDFStore(filename,'r') as store:
self.data = store['mydata']
self.metadata = store.get_storer('mydata').attrs.metadata # metadata gets stored as attributes, so no need to make <metadata> an attribute of <self>
# put metadata into <data> dataframe as attributes
for r in self.metadata:
setattr(self,r,self.metadata[r])
# unscale data
self.data, self.metadata = unscale(self.data,self.metadata,stringcols=['routine','date'])
# when pandas stores multi-index dataframes as H5 files the timezone
# initialization is lost. Remake index with timezone initialized: only
# for multi-indexed dataframes
if isinstance(self.data.index,pd.core.index.MultiIndex):
# list index-level names, and identify 'DATE' level
namen = self.data.index.names
date_lev = namen.index('DATE')
# extract index as list and remake tuples with timezone initialized
new_index = pd.MultiIndex.tolist(self.data.index)
for r in xrange( len(new_index) ):
tmp = list( new_index[r] )
tmp[date_lev] = utc.localize( tmp[date_lev] )
new_index[r] = tuple(tmp)
# reset multi-index
self.data.index = pd.MultiIndex.from_tuples( new_index, names=namen )
if update:
return self.metadata, self.data
else:
return self
def h5store(self,data, filename, **kwargs):
'''h5store stores the dataframe as an HDF5 file. Both the dataframe
(actual data) and the associated metadata are stored in the H5file
Parameters
----------
data : Pandas dataframe NOT a class instance
Must be a dataframe, not a class instance (i.e. cannot be an instance
named <data> that has an attribute named <data> (e.g. the Pandas
data frame is stored in data.data)). If the dataframe is under
data.data then the input variable must be data.data.
filename : string/path
path and filename of H5 file to be loaded. H5 file must have been
created using <h5store> below.
**kwargs : dictionary
dictionary containing metadata information.
Output
------
None: only saves data to file'''
with pd.HDFStore(filename,'w') as store:
store.put('mydata',data)
store.get_storer('mydata').attrs.metadata = kwargs
Les fichiers H5 sont ensuite chargés via data = IO().h5load('nom du fichier.h5") la base de données est stockée sous data.données Je conserve les métadonnées dictionnaire données.métadonnées et ont créé des attributs de métadonnées individuels (p. ex. des données.lat créé à partir de données.les métadonnées['lat']).
Mon index, les horodateurs sont localisées à pytz.utc (). Cependant, quand une dataframe multi-indexée est stockée à h5 la localisation du fuseau horaire est perdue (en utilisant Pandas 15.2), donc je corrige pour cela dans IO ().h5load.
2 réponses
il y a une question ouverte concernant le stockage de métadonnées personnalisées dans NDFrames. Mais en raison de la multitude de façons dont les fonctions pandas peuvent retourner les DataFrames, l'attribut _metadata
n'est pas (encore) conservé dans toutes les situations.
Pour le moment, vous aurez juste à stocker les métadonnées dans une variable auxiliaire.
il existe plusieurs options pour stocker des images de données + métadonnées dans des fichiers, selon le format vous souhaitez utiliser -- pickle, JSON, HDF5 sont toutes les possibilités.
Voici comment vous pouvez stocker et charger une base de données avec des métadonnées en utilisant HDF5. La recette pour stocker les métadonnées provient du Pandas Cookbook .
import numpy as np
import pandas as pd
def h5store(filename, df, **kwargs):
store = pd.HDFStore(filename)
store.put('mydata', df)
store.get_storer('mydata').attrs.metadata = kwargs
store.close()
def h5load(store):
data = store['mydata']
metadata = store.get_storer('mydata').attrs.metadata
return data, metadata
a = pd.DataFrame(
data=pd.np.random.randint(0, 100, (10, 5)), columns=list('ABCED'))
filename = '/tmp/data.h5'
metadata = dict(local_tz='US/Eastern')
h5store(filename, a, **metadata)
with pd.HDFStore(filename) as store:
data, metadata = h5load(store)
print(data)
# A B C E D
# 0 9 20 92 43 25
# 1 2 64 54 0 63
# 2 22 42 3 83 81
# 3 3 71 17 64 53
# 4 52 10 41 22 43
# 5 48 85 96 72 88
# 6 10 47 2 10 78
# 7 30 80 3 59 16
# 8 13 52 98 79 65
# 9 6 93 55 40 3
print(metadata)
rendements
{'local_tz': 'US/Eastern'}
l'approche que j'utilise est d'ajouter des niveaux supplémentaires MultiIndex
pour stocker les informations supplémentaires que je veux (j'utilise les colonnes, mais l'un ou l'autre fonctionnerait). Toutes les colonnes ont les mêmes valeurs pour ces paramètres supplémentaires. Ceci est également utile car je peux combiner plusieurs dataframes ou séparer des colonnes individuelles et ces valeurs sont préservées.
>>> col=pd.MultiIndex.from_product([['US/Eastern'], ['A', 'B', 'C', 'E', 'D']], names=['local_tz', 'name'])
>>> a = pd.DataFrame(data=pd.np.random.randint(0,100,(10,5)),columns=col)
>>> print(a)
local_tz US/Eastern
name A B C E D
0 38 93 63 24 55
1 21 25 84 98 62
2 4 60 78 0 5
3 26 50 82 89 23
4 32 70 80 90 1
5 6 17 8 60 59
6 95 98 69 19 76
7 71 90 45 45 40
8 94 16 44 60 16
9 53 8 30 4 72