Almacenamiento de pandas DataFrame con datos y categorías mixtas en hdf5

Quiero almacenar un dataFrame con diferentes columnas en un archivo hdf5 (encuentre un extracto con los tipos de datos a continuación).

In [1]: mydf Out [1]: endTime uint32 distance float16 signature category anchorName category stationList object 

Antes de convertir algunas columnas (firma y anchorName en mi extracto anterior), utilicé un código como el siguiente para almacenarlo (que funciona bastante bien):

 path = 'tmp4.hdf5' key = 'journeys' mydf.to_hdf(path, key, mode='w', complevel=9, complib='bzip2') 

Pero no funciona con la categoría y luego intenté seguir:

 path = 'tmp4.hdf5' key = 'journeys' mydf.to_hdf(path, key, mode='w', format='t', complevel=9, complib='bzip2') 

Funciona bien, si elimino la columna stationList, donde cada entrada es una lista de cadenas. Pero con esta columna obtuve la siguiente excepción:

 Cannot serialize the column [stationList] because its data contents are [mixed] object dtype 

¿Cómo necesito mejorar mi código para almacenar el dataframe?

versión pandas: 0.17.1
Versión de Python: 2.7.6 (no se puede cambiar debido a razones de compatibilidad)


edit1 (algunos ejemplos de código):

 import pandas as pd mydf = pd.DataFrame({'endTime' : pd.Series([1443525810,1443540836,1443609470]), 'distance' : pd.Series([454.75,477.25,242.12]), 'signature' : pd.Series(['ab','cd','ab']), 'anchorName' : pd.Series(['tec','ing','pol']), 'stationList' : pd.Series([['t1','t2','t3'],['4','t2','t3'],['t3','t2','t4']]) }) # this works fine (no category) mydf.to_hdf('tmp_without_cat.hdf5', 'journeys', mode='w', complevel=9, complib='bzip2') for col in ['anchorName', 'signature']: mydf[col] = mydf[col].astype('category') # this crashes now because of category data # mydf.to_hdf('tmp_with_cat.hdf5', 'journeys', mode='w', complevel=9, complib='bzip2') # switching to format='t' # this caused problems because of "mixed data" in column stationList mydf.to_hdf('tmp_with_cat.hdf5', 'journeys', mode='w', format='t', complevel=9, complib='bzip2') mydf.pop('stationList') # this again works fine mydf.to_hdf('tmp_with_cat_without_stationList.hdf5', 'journeys', mode='w', format='t', complevel=9, complib='bzip2') 

edit2: Mientras tanto, intenté diferentes cosas para deshacerme de este problema. Uno de ellos fue convertir las entradas de la columna stationList a tupels (es posible, ya que no deben modificarse) y también convertirlas a la categoría. Pero no cambió nada. Aquí están las líneas que agregué después del ciclo de conversión (solo para completar):

 mydf.stationList = [tuple(x) for x in mydf.stationList.values] mydf.stationList.astype('category') 

Tienes dos problemas:

  1. Desea almacenar datos categóricos en un archivo HDF5;
  2. Está intentando almacenar objetos arbitrarios (es decir, stationList ) en un archivo HDF5.

Como descubrió, los datos categóricos (actualmente?) Solo se admiten en el formato de “tabla” para HDF5.

Sin embargo, almacenar objetos arbitrarios (lista de cadenas, etc.) realmente no es algo que sea compatible con el formato HDF5 en sí. Las pandas trabajan alrededor de eso para usted mediante la serialización de estos objetos utilizando pickle, y luego almacenan el pickle como una cadena de longitud arbitraria (que no es compatible con todos los formatos HDF5, creo). Pero eso será lento e ineficiente, y nunca será soportado bien por HDF5.

En mi mente, tienes dos opciones:

  1. Gire sus datos para que tenga una fila de datos por nombre de estación. Luego, puede almacenar todo en un archivo HDF5 en formato de tabla. (Esta es una buena práctica en general; consulte a Hadley Wickham en Tidy Data ).
  2. Si realmente desea mantener este formato, también puede guardar todo el dataframe utilizando to_pickle (). Esto no tendrá ningún problema al tratar con cualquier tipo de objeto (p. Ej., Lista de cadenas, etc.) que le arrojas.

Personalmente, recomendaría la opción 1. Puede utilizar un formato de archivo binario rápido. Y el pivote también facilitará otras operaciones con sus datos.