Saltar al contenido

Aprende (funcionalidad básica de) PyTables paso a paso (II)

En el anterior capítulo vimos como crear una estructura básica para nuestro fichero h5. Ahora vamos a ver como rellenar tablas de ese mismo fichero.

Rellenar tablas

Ahora es tiempo de rellenar la tabla con datos sin sentido (datos aleatorios) y fechas. numpy y datetime nos facilitarán la tarea por lo que vamos a importarlos antes).

import numpy as np
import datetime as dt

Abrimos de nuevo el fichero h5 que creamos en el anterior capítulo, pero en lugar de abrirlo en modo “write” lo abriremos en modo “append”.

h5file = tb.open_file("tabla_test.h5", mode="a")

Recuperamos la tabla que queremos llenar (indicando la ruta en la estructura del fichero hdf5) y usando la función getNode:

tab = h5file.get_node("/carpeta1/datos_carpeta1_tabla1")

Para rellenar la tabla creamos un puntero (o constructor de líneas propio a la tabla) row.

mis_datos = tab.row

Creamos los datos que usaremos para rellenar la tabla:

f0 = dt.date(2000, 1, 1)
fechas = np.array(
    [int((f0 + dt.timedelta(days=1) * i).strftime("%Y%m%d")) for i in range(10000)],
    dtype = np.int32
)
x = np.random.randn(10000)
y = np.random.randn(10000)
z = np.random.randn(10000)

Llenamos la tabla de manera recursiva con el constructor de líneas mis_datos y el método append:

for i in range(10000):
    mis_datos['fecha'] = fechas[i]
    mis_datos['x'] = x[i]
    mis_datos['y'] = y[i]
    mis_datos['z'] = z[i]
    mis_datos.append()

Se llama al método flush sobre la tabla para volcar y registrar efectivamente los datos en la tabla.

tab.flush()

Si queremos, podemos añadir meta-información a la tabla:

tab.attrs.nombre_sensor="medidas de un escaterómetro"
tab.attrs.numero_columnas = 3

Además de la meta-información que hemos añadido, el objeto tabla contenía ya un cierto número de atributos que podemos ver escribiendo lo siguiente en IPython

tab.attrs

que nos mostrará lo siguiente:

/carpeta1/datos_carpeta1_tabla1._v_attrs (AttributeSet), 14 attributes:
   [CLASS := 'TABLE',
   FIELD_0_FILL := 0,
   FIELD_0_NAME := 'fecha',
   FIELD_1_FILL := 0.0,
   FIELD_1_NAME := 'x',
   FIELD_2_FILL := 0.0,
   FIELD_2_NAME := 'y',
   FIELD_3_FILL := 0.0,
   FIELD_3_NAME := 'z',
   NROWS := 0,
   TITLE := 'ejemplo de tabla',
   VERSION := '2.7',
   nombre_sensor := 'medidas de un escaterómetro',
   numero_columnas := 3]

Finalmente, cerramos la tabla creada como vimos en el primer capítulo.

h5file.close()

Si queréis usar una aplicación gráfica para ver el alrchivo que hemos creado podéis usar hdfview (sudo apt-get install hdfview) o vitables. En este caso os muestro un ejemplo con hdfview ya que vitables posíblemente lo veamos en uno de los próximos capítulos.

Bueno, ya tenemos algunos datos guardados en nuestro fichero HDF5. El próximo día veremos como anexar datos a una tabla ya existente.

Saludos.

3 comentarios en «Aprende (funcionalidad básica de) PyTables paso a paso (II)»

  1. Realmente muy ameno para trabajar. Muchas gracias Kiko!!!
    En el puntero de datos ¿es igual de eficiente, si en el for se pone “tab.row[‘x’] = x[i]”? ya que tab.row es un método (con cara de parámetro), o es mejor evaluarlo una ves (mis_datos = tab.row) y luego usar esa variable directamente (como has hecho).

  2. Hola, schriher.
    row es un método de la clase Table pero a la vez es una clase escrita en Cython. Si haces:
    print(type(tab.row)) # o print(type(mis_datos))
    deberías ver:
    class ‘tables.tableextension.Row’
    (método row de la clase Table: https://github.com/PyTables/PyTables/blob/develop/tables/table.py#L594)
    (código Cython de la clase Row: https://github.com/PyTables/PyTables/blob/4b6c0f4000c9e3621668583d09b144c781051e89/tables/tableextension.pyx#L672)
    En la forma que tú dices, estás llamando al método cada vez que quieres insertar una nueva fila y eso puede ser más ‘caro’ que instanciar una vez la clase Row (que es un iterador).
    Puedes hacer tú mismo una prueba rápida (lo siguiente está hecho en IPyhon3 en mi equipo):
    ##### AVISO: El siguiente código puede crear varios millones de filas nuevas en tu fichero h5
    [sourcecode language=”python”]
    def kk():
    for i in range(2000):
    mis_datos[‘fecha’] = fechas[i]
    mis_datos[‘x’] = x[i]
    mis_datos[‘y’] = y[i]
    mis_datos[‘z’] = z[i]
    mis_datos.append()
    tab.flush()
    def kk1():
    for i in range(2000):
    tab.row[‘fecha’] = fechas[i]
    tab.row[‘x’] = x[i]
    tab.row[‘y’] = y[i]
    tab.row[‘z’] = z[i]
    tab.row.append()
    tab.flush()
    %timeit kk()
    %timeit kk1()
    [/sourcecode]
    La primera forma, kk, que es como se indica en el tutorial y en la documentación oficial de PyTables, nos da lo siguiente:
    1000 loops, best of 3: 1.85 ms per loop
    Mientras que la forma que propones tú, kk1, nos da el siguiente resultado:
    100 loops, best of 3: 4.17 ms per loop
    por lo que sería entre 2 y 3 veces más lento.

    1. Muchas gracias Kiko! mas o menos eso pensaba, pero no se me había ocurrido probarlo así, excelente!!!
      Solo un detalle si el Aviso tenia la intensión de hacerme pensar antes de probar fue todo lo contrario, leí Aviso y abrí un terminal para probarlo jejeje el archivo terminó con mas de 160 MB.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

+ 88 = ninety

Pybonacci