Estoy tratando de leer unos cientos de tablas de ascii y luego escribirlas en mySQL. Parece fácil de hacer con Pandas, pero cometí un error que no tiene sentido para mí:
Tengo un dataframe de 8 columnas. Aquí está la lista de columnas / índice:
metricDF.columns Index([u'FID', u'TYPE', u'CO', u'CITY', u'LINENO', u'SUBLINE', u'VALUE_010', u'VALUE2_015'], dtype=object)
Luego uso to_sql
para agregar los datos a mySQL
metricDF.to_sql(con=con, name=seqFile, if_exists='append', flavor='mysql')
Me sale un error extraño de que una columna es “nan”:
OperationalError: (1054, "Unknown column 'nan' in 'field list'")
Como puedes ver todas mis columnas tienen nombres. Me doy cuenta de que el soporte de mysql / sql para escritura aparece en desarrollo, así que quizás esa sea la razón ¿Si es así, hay alguna solución? Cualquier sugerencia sería muy apreciada.
Actualización : a partir de pandas 0.15, to_sql
admite la escritura de valores NaN
(se escribirán como NULL
en la base de datos), por lo que la solución que se describe a continuación ya no será necesaria (consulte https://github.com/pydata/pandas/pull/ 8208 ).
Pandas 0.15 se lanzará en octubre próximo, y la característica se fusiona en la versión de desarrollo.
Esto se debe probablemente a los valores de NaN
en su tabla, y este es un defecto conocido en el momento en que las funciones de pandas sql no manejan bien los NaN ( https://github.com/pydata/pandas/issues/2754 , https: //github.com/pydata/pandas/issues/4199 )
Como solución temporal en este momento (para las versiones de pandas 0.14.1 y anteriores), puede convertir manualmente los valores de nan
a Ninguno con:
df2 = df.astype(object).where(pd.notnull(df), None)
y luego escribir el dataframe a SQL. Sin embargo, esto convierte todas las columnas al tipo de objeto. Debido a esto, debe crear la tabla de base de datos basada en el dataframe original. Por ejemplo, si su primera fila no contiene NaN
s:
df[:1].to_sql('table_name', con) df2[1:].to_sql('table_name', con, if_exists='append')
el uso de la solución anterior cambiará el tipo de columna de float64 a object_.
He encontrado una mejor solución, solo agregue la siguiente función _write_mysql:
from pandas.io import sql def _write_mysql(frame, table, names, cur): bracketed_names = ['`' + column + '`' for column in names] col_names = ','.join(bracketed_names) wildcards = ','.join([r'%s'] * len(names)) insert_query = "INSERT INTO %s (%s) VALUES (%s)" % ( table, col_names, wildcards) data = [[None if type(y) == float and np.isnan(y) else y for y in x] for x in frame.values] cur.executemany(insert_query, data)
Y luego anula su implementación en pandas como se muestra a continuación:
sql._write_mysql = _write_mysql
Con este código, los valores de nan se guardarán correctamente en la base de datos sin alterar el tipo de columna.
NaT a MySQL aún no se maneja en pandas 15.2