¿Es posible agregar algo de metainformación / metadatos a un DataFrame de pandas?
Por ejemplo, el nombre del instrumento utilizado para medir los datos, el instrumento responsable, etc.
Una solución alternativa sería crear una columna con esa información, ¡pero parece un desperdicio almacenar una sola pieza de información en cada fila!
Respuestas:
Claro, como la mayoría de los objetos de Python, puede adjuntar nuevos atributos a
pandas.DataFrame
:import pandas as pd df = pd.DataFrame([]) df.instrument_name = 'Binky'
Nótese, sin embargo, que si bien puede adjuntar atributos a una trama de datos, las operaciones realizadas en la trama de datos (como
groupby
,pivot
,join
oloc
para nombrar sólo algunos) puede devolver una nueva trama de datos , sin los metadatos adjunto. Pandas aún no tiene un método sólido para propagar metadatos adjuntos a DataFrames .Es posible conservar los metadatos en un archivo . Puede encontrar un ejemplo de cómo almacenar metadatos en un archivo HDF5 aquí .
fuente
store = pd.HDFStore(...)
, los atributos se pueden almacenar constore.root._v_attrs.key = value
.df = pd.DataFrame(); df.meta = {}
produceUserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
). (No se da ninguna advertencia si el atributo ya se ha creado como endf = pd.DataFrame(); df.meta = ''; df.meta = {}
).Me encontré con este problema yo mismo. A partir de pandas 0.13, los DataFrames tienen un atributo _metadata que persiste a través de funciones que devuelven nuevos DataFrames. También parece sobrevivir a la serialización bien (solo he probado json, pero imagino que hdf también está cubierto).
fuente
_metadata
no es parte de la API pública, por lo que recomiendo encarecidamente no confiar en esta funcionalidad..attrs
es parte de la API de xray)_metadata
es en realidad un atributo de clase, no un atributo de instancia. Entonces, las nuevasDataFrame
instancias heredan de las anteriores, siempre que el módulo permanezca cargado. No lo use_metadata
para nada. +1 paraxarray
!Realmente no. Aunque puede agregar atributos que contienen metadatos a la clase DataFrame como menciona @unutbu, muchos métodos DataFrame devuelven un nuevo DataFrame, por lo que sus metadatos se perderían. Si necesita manipular su marco de datos, la mejor opción sería envolver sus metadatos y su marco de datos en otra clase. Vea esta discusión en GitHub: https://github.com/pydata/pandas/issues/2485
Actualmente hay una solicitud de extracción abierta para agregar un objeto MetaDataFrame, que admitiría mejor los metadatos.
fuente
A partir de pandas 1.0, posiblemente antes, ahora hay una
Dataframe.attrs
propiedad. Es experimental, pero probablemente esto es lo que querrás en el futuro. Por ejemplo:import pandas as pd df = pd.DataFrame([]) df.attrs['instrument_name'] = 'Binky'
Encuéntrelo en los documentos aquí .
Probar esto con
to_parquet
y luegofrom_parquet
, no parece persistir, así que asegúrese de verificarlo con su caso de uso.fuente
dataclass
para los metadatos y luegoDataFrame
crear una subclasificación para tener un método que realice la carga / descarga como en la publicación que compartió podría ser una buena solución.La respuesta principal de adjuntar atributos arbitrarios al objeto DataFrame es buena, pero si usa un diccionario, lista o tupla, emitirá un error de "Pandas no permite que se creen columnas a través de un nuevo nombre de atributo". La siguiente solución funciona para almacenar atributos arbitrarios.
from types import SimpleNamespace df = pd.DataFrame() df.meta = SimpleNamespace() df.meta.foo = [1,2,3]
fuente
pd.DataFrame._metadata += ["meta"]
. Tenga en cuenta que esta parte es un atributo de Pandas, no un atributo de su marco de datos específicodf.meta
activa una advertencia de que Pandas no permite que se generen nuevas columnas de esta manera.df.meta
es un SimpleNamespace. Pandas no intentará construir una columna a partir de él.Como se mencionó en otras respuestas y comentarios,
_metadata
no es parte de la API pública, por lo que definitivamente no es una buena idea usarla en un entorno de producción. Pero es posible que aún desee utilizarlo en un prototipo de investigación y reemplazarlo si deja de funcionar. Y ahora mismo funciona congroupby
/apply
, lo cual es útil. Este es un ejemplo (que no pude encontrar en otras respuestas):df = pd.DataFrame([1, 2, 2, 3, 3], columns=['val']) df.my_attribute = "my_value" df._metadata.append('my_attribute') df.groupby('val').apply(lambda group: group.my_attribute)
Salida:
val 1 my_value 2 my_value 3 my_value dtype: object
fuente
Llegando bastante tarde a esto, pensé que esto podría ser útil si necesita que los metadatos persistan en la E / S. Hay un paquete relativamente nuevo llamado h5io que he estado usando para lograr esto.
Debería permitirle hacer una lectura / escritura rápida desde HDF5 para algunos formatos comunes, uno de ellos es un marco de datos. Entonces, puede, por ejemplo, poner un marco de datos en un diccionario e incluir metadatos como campos en el diccionario. P.ej:
save_dict = dict(data=my_df, name='chris', record_date='1/1/2016') h5io.write_hdf5('path/to/file.hdf5', save_dict) in_data = h5io.read_hdf5('path/to/file.hdf5') df = in_data['data'] name = in_data['name'] etc...
Otra opción sería buscar en un proyecto como Xray , que es más complejo en algunos aspectos, pero creo que te permite usar metadatos y es bastante fácil de convertir a un DataFrame.
fuente
Como lo menciona @choldgraf, he descubierto que xarray es una excelente herramienta para adjuntar metadatos al comparar datos y trazar resultados entre varios marcos de datos.
En mi trabajo, a menudo comparamos los resultados de varias revisiones de firmware y diferentes escenarios de prueba, agregar esta información es tan simple como esto:
df = pd.read_csv(meaningless_test) metadata = {'fw': foo, 'test_name': bar, 'scenario': sc_01} ds = xr.Dataset.from_dataframe(df) ds.attrs = metadata
fuente
He estado buscando una solución y descubrí que pandas frame tiene la propiedad
attrs
pd.DataFrame().attrs.update({'your_attribute' : 'value'}) frame.attrs['your_attribute']
¡Este atributo siempre se adherirá a su marco cada vez que lo pase!
fuente
Tenía el mismo problema y usé una solución alternativa para crear un DF nuevo y más pequeño a partir de un diccionario con los metadatos:
meta = {"name": "Sample Dataframe", "Created": "19/07/2019"} dfMeta = pd.DataFrame.from_dict(meta, orient='index')
Este dfMeta se puede guardar junto con su DF original en pickle, etc.
Consulte ¿ Guardar y cargar varios objetos en un archivo pickle? (Respuesta de Lutz) para una excelente respuesta sobre cómo guardar y recuperar múltiples marcos de datos usando pickle
fuente