python - importar - leer archivos con pandas
Guardar en un archivo una matriz o DataFrame junto con otra informaciĆ³n (6)
Es una pregunta interesante, aunque creo que es muy abierta.
Fragmentos de texto
Para fragmentos de texto que tienen notas literales (como en, no código y no datos), realmente no sé cuál es su caso de uso, pero no veo por qué me desviaría de usar lo habitual with open() as f: ...
Pequeñas colecciones de varias piezas de datos.
Claro, tu npz
funciona. En realidad, lo que está haciendo es muy similar a crear un diccionario con todo lo que desea guardar y decapar ese diccionario.
Vea here para una discusión de las diferencias entre pickle y npz (pero principalmente, npz está optimizado para matrices numpy).
Personalmente, diría que si no está almacenando arreglos Numpy, usaría pickle, e incluso implementaría una clase rápida de MyNotes
que es básicamente un diccionario para guardar cosas, con algunas funciones adicionales que pueda desear.
Colección de objetos grandes.
Para np.rasys realmente grandes o marcos de datos que he usado antes del formato HDF5. Lo bueno es que ya está integrado en pandas y puedes directamente df.to_hdf5()
. Es necesario que pytables
debajo de pytables
instalación debería ser bastante indolora con pip o conda), pero usar pytables directamente puede ser un dolor mucho mayor.
Una vez más, esta idea es muy similar: está creando un HDFStore, que es prácticamente un gran diccionario en el que puede almacenar (casi cualquier) objeto. El beneficio es que el formato utiliza el espacio de una manera más inteligente al aprovechar la repetición de valores similares. Cuando lo estaba usando para almacenar algunos marcos de datos de ~ 2GB, fue capaz de reducirlo en casi un orden de magnitud (~ 250 MB).
Un último jugador: la feather
Feather
es un proyecto creado por Wes McKinney y Hadley Wickham en la parte superior del marco de Apache Arrow, para conservar los datos en un formato binario que es agnóstico del lenguaje (y, por lo tanto, puede leer desde R y Python). Sin embargo, aún está en desarrollo, y la última vez que verifiqué no recomendaron usarlo para el almacenamiento a largo plazo (ya que la especificación puede cambiar en futuras versiones), en lugar de solo usarlo para la comunicación entre R y Python.
Ambos acaban de lanzar Ursalabs , literalmente, hace unas semanas, que continuarán creciendo esta y otras iniciativas similares.
El software estadístico Stata permite que se guarden fragmentos de texto cortos dentro de un conjunto de datos. Esto se logra mediante el uso de notes
y / o characteristics
.
Esta es una característica de gran valor para mí, ya que me permite guardar una variedad de información, desde recordatorios y listas de tareas hasta información sobre cómo generé los datos, o incluso cuál fue el método de estimación para una variable en particular.
Ahora estoy tratando de encontrar una funcionalidad similar en Python 3.6. Hasta ahora, he mirado en línea y he consultado una serie de publicaciones que, sin embargo, no abordan exactamente lo que quiero hacer.
Algunas publicaciones de referencia incluyen:
¿Cuál es la diferencia entre guardar un marco de datos de pandas en pickle y csv?
¿Cómo veo el contenido del objeto de datos dentro de un archivo npz?
Para una pequeña matriz NumPy
, he concluido que una combinación de la función numpy.savez()
y un dictionary
puede almacenar adecuadamente toda la información relevante en un solo archivo.
Por ejemplo:
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()
Sin embargo, la pregunta sigue siendo:
¿Hay mejores formas de incorporar potencialmente otras piezas de información en un archivo que contenga una matriz NumPy
o un Pandas
DataFrame
(grande)?
Estoy particularmente interesado en conocer los pros y los contras particulares de cualquier sugerencia que pueda tener con ejemplos. Cuantas menos dependencias, mejor.
Estoy de acuerdo con JPP en que el almacenamiento en hdf5 es una buena opción aquí. La diferencia entre su solución y la mía es que la mía utiliza los marcos de datos de Pandas en lugar de las matrices numpy. Prefiero el marco de datos ya que esto permite tipos mixtos, indexación multinivel (incluso indexación de fecha y hora, que es MUY importante para mi trabajo), y etiquetado de columnas, que me ayuda a recordar cómo se organizan los diferentes conjuntos de datos. Además, Pandas proporciona una gran cantidad de funcionalidades incorporadas (como el numpy). Otra ventaja de usar Pandas es que tiene un creador de hdf integrado (es decir, pandas.DataFrame.to_hdf), que me parece conveniente
Cuando almacena el marco de datos en h5, tiene la opción de almacenar también un diccionario de metadatos, que pueden ser sus notas, o metadatos reales que no necesitan ser almacenados en el marco de datos (yo también uso esto para establecer marcas, por ejemplo, {''is_agl'': True, ''scale_factor'': 100, ''ya_corrected'': False, etc.}. En este sentido, no hay diferencia entre usar una matriz numpy y un marco de datos. Para la solución completa, vea mi pregunta original y solución aquí
Hay muchas opciones. Discutiré solo HDF5, porque tengo experiencia en el uso de este formato.
Ventajas : Portátil (se puede leer fuera de Python), compresión nativa, capacidades de memoria insuficiente, soporte de metadatos.
Desventajas : la dependencia de la API de C de bajo nivel, la posibilidad de corrupción de datos como un solo archivo, eliminar datos no reduce el tamaño automáticamente.
En mi experiencia, para el rendimiento y la portabilidad, evite pyTables
/ HDFStore
para almacenar datos numéricos. En su lugar, puede utilizar la interfaz intuitiva proporcionada por h5py
.
Almacenar una matriz
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)
Compresión y fragmentación
Hay muchas opciones de compresión, por ejemplo, blosc
y lzf
son buenas opciones para el rendimiento de compresión y descompresión respectivamente. Note que gzip
es nativo; Es posible que otros filtros de compresión no se envíen de forma predeterminada con su instalación HDF5.
La fragmentación es otra opción que, cuando se alinea con la forma en que se leen los datos sin memoria, puede mejorar significativamente el rendimiento.
Añadir algunos atributos
dset.attrs[''Description''] = ''Some text snippet''
dset.attrs[''RowIndexArray''] = np.arange(1000)
Almacenar un diccionario
for k, v in d.items():
f.create_dataset(''dictgroup/''+str(k), data=v)
Acceso fuera de la memoria
dictionary = f[''dictgroup'']
res = dictionary[''my_key'']
No hay sustituto para leer la h5py h5py
, que expone la mayor parte de la API de C, pero debería ver que, a partir de lo anterior, hay una cantidad significativa de flexibilidad.
La respuesta de jpp es bastante completa, solo quiero mencionar que a partir de Pandas V22 Parquet es una opción muy conveniente y rápida, casi sin inconvenientes frente a CSV (acepte quizás la pausa del café).
Al momento de escribir, también necesitarás
pip install pyarrow
En términos de agregar información, usted tiene los metadatos que se adjuntan a los datos.
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''}
Para devolver esto a los pandas:
tab.to_pandas()
Una forma práctica podría ser incrustar metadatos directamente dentro de la matriz Numpy. La ventaja es que, como desearía, no hay dependencia adicional y es muy fácil de usar en el código. Sin embargo, esto no responde completamente a su pregunta, ya que todavía necesita un mecanismo para guardar los datos, y le recomiendo usar la solución de jpp utilizando HDF5.
Para incluir metadatos en un ndarray
, hay un ejemplo en la documentación . Básicamente tienes que subclasificar un ndarray
y agregar una info
campo o metadata
o lo que sea.
Daría (código del enlace de arriba)
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)
Para guardar los datos a través del numpy
, deberá sobrecargar la función de write
o usar otra solución.
Usted declaró como las razones de esta pregunta:
... me permite guardar una variedad de información, desde recordatorios y listas de tareas pendientes, hasta información sobre cómo generé los datos, o incluso cuál fue el método de estimación para una variable en particular .
¿Puedo sugerir un paradigma diferente al ofrecido por Stata? Las notas y las características parecen ser muy limitadas y se limitan a solo texto. En su lugar, debe usar el cuaderno Jupyter para sus proyectos de investigación y análisis de datos. Proporciona un entorno tan rico para documentar su flujo de trabajo y capturar detalles, pensamientos e ideas mientras realiza su análisis e investigación. Se puede compartir fácilmente y está listo para la presentación.
Aquí hay una galería de interesantes cuadernos Jupyter en muchas industrias y disciplinas para mostrar las muchas características y casos de uso de los cuadernos. Puede expandir sus horizontes más allá de intentar idear una forma de etiquetar fragmentos de texto simples a sus datos.