¿Cómo escribir DataFrame en la tabla de postgres?

Existe el método DataFrame.to_sql , pero funciona solo para las bases de datos mysql, sqlite y oracle. No puedo pasar a este método postgres connection o sqlalchemy engine.

A partir de pandas 0.14 (lanzado a finales de mayo de 2014), se admite postgresql. El módulo sql ahora usa sqlalchemy para soportar diferentes tipos de bases de datos. Puede pasar un motor sqlalchemy para una base de datos postgresql (ver documentos ). P.ej:

 from sqlalchemy import create_engine engine = create_engine('postgresql://scott:tiger@localhost:5432/mydatabase') df.to_sql('table_name', engine) 

Tienes razón en que en pandas hasta la versión 0.13.1 postgresql no era compatible. Si necesita usar una versión anterior de pandas, aquí hay una versión parcheada de pandas.io.sql : https://gist.github.com/jorisvandenbossche/10841234 .
Escribí esto hace un tiempo, así que no puedo garantizar completamente que siempre funciona, pero la base debería estar ahí). Si coloca ese archivo en su directorio de trabajo y lo importa, entonces debería poder hacerlo (donde con es una conexión postgresql):

 import sql # the patched version (file is named sql.py) sql.write_frame(df, 'table_name', con, flavor='postgresql') 

Opción más rápida:

El siguiente código copiará su Pandas DF a DB postgres mucho más rápido que el método df.to_sql y no necesitará ningún archivo csv intermedio para almacenar el df.

Crea un motor basado en tus especificaciones DB.

Cree una tabla en su base de datos de Postgres que tenga el mismo número de columnas que el Dataframe (df).

Los datos en DF se insertarán en su tabla de postgres.

 from sqlalchemy import create_engine import psycopg2 import io 

Si desea reemplazar la tabla, podemos reemplazarla con el método normal de to_sql usando encabezados de nuestro df y luego cargar todo el df que consume mucho tiempo en la base de datos.

 engine = create_engine('postgresql+psycopg2://username:password@host:port/database') df.head(0).to_sql('table_name', engine, if_exists='replace',index=False) #truncates the table conn = engine.raw_connection() cur = conn.cursor() output = io.StringIO() df.to_csv(output, sep='\t', header=False, index=False) output.seek(0) contents = output.getvalue() cur.copy_from(output, 'table_name', null="") # null values become '' conn.commit() 

Así es como lo hago, puedo ser más rápido porque está utilizando execute_batch:

 # df is the dataframe if len(df) > 0: df_columns = list(df) # create (col1,col2,...) columns = ",".join(df_columns) # create VALUES('%s', '%s",...) one '%s' per column values = "VALUES({})".format(",".join(["%s" for _ in df_columns])) #create INSERT INTO table (columns) VALUES('%s',...) insert_stmt = "INSERT INTO {} ({}) {}".format(table,columns,values) cur = conn.cursor() cur = db_conn.cursor() psycopg2.extras.execute_batch(cur, insert_stmt, df.values) conn.commit() cur.close() 

Pandas 0.24.0+ solución

En Pandas 0.24.0 se introdujo una nueva característica diseñada específicamente para escrituras rápidas en Postgres. Puede obtener más información al respecto aquí: https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html#io-sql-method

 import csv from io import StringIO from sqlalchemy import create_engine def psql_insert_copy(table, conn, keys, data_iter): # gets a DBAPI connection that can provide a cursor dbapi_conn = conn.connection with dbapi_conn.cursor() as cur: s_buf = StringIO() writer = csv.writer(s_buf) writer.writerows(data_iter) s_buf.seek(0) columns = ', '.join('"{}"'.format(k) for k in keys) if table.schema: table_name = '{}.{}'.format(table.schema, table.name) else: table_name = table.name sql = 'COPY {} ({}) FROM STDIN WITH CSV'.format( table_name, columns) cur.copy_expert(sql=sql, file=s_buf) engine = create_engine('postgresql://myusername:mypassword@myhost:5432/mydatabase') df.to_sql('table_name', engine, method=psql_insert_copy)