Respuestas:
A partir de pandas 0.14 (lanzado a finales de mayo de 2014), se admite postgresql. El sql
módulo ahora se usa sqlalchemy
para admitir 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)
Tiene 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, por lo que no puedo garantizar completamente que siempre funcione, pero la base debería estar ahí). Si coloca ese archivo en su directorio de trabajo y lo importa, entonces debería poder hacer (dónde con
está una conexión postgresql):
import sql # the patched version (file is named sql.py)
sql.write_frame(df, 'table_name', con, flavor='postgresql')
Sqlalchemy engine
, ¿puedo utilizar una Postgres
conexión existente creada con psycopg2.connect()
?
Opción más rápida:
El siguiente código copiará su Pandas DF a postgres DB mucho más rápido que el método df.to_sql y no necesitará ningún archivo csv intermedio para almacenar el df.
Cree un motor basado en las especificaciones de su base de datos.
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 to_sql normal usando encabezados de nuestro df y luego cargar todo el df que consume mucho tiempo en DB.
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()
contents
? ¿Debería ser este el que está escrito copy_from()
?
contents
variable, todo lo demás debería funcionar bien
output.seek(0)
?
Solución Pandas 0.24.0+
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)
method='multi'
opciones es lo suficientemente rápido. Pero sí, este COPY
método es el más rápido en este momento.
with
escribir en un búfer de memoria. La última parte del proceso with
consiste en utilizar una declaración SQL y aprovechar la velocidad de copy_expert para cargar los datos de forma masiva. ¿Cuál es la parte intermedia que comienza con columns =
hacer?
keys
argumentos en la psql_insert_copy
función por favor? ¿Cómo obtiene las claves y son las claves solo los nombres de las columnas?
Table 'XYZ' already exists
. Por lo que tengo entendido, no debería crear una tabla, ¿verdad?
df.to_sql('table_name', engine, if_exists='replace', method=psql_insert_copy)
- esto crea una tabla en su base de datos.
Así es como lo hice.
Puede ser más rápido porque usa 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()
psycopg2.extras.execute_batch(cur, insert_stmt, df.values)
conn.commit()
cur.close()
Para Python 2.7 y Pandas 0.24.2 y usando Psycopg2
Módulo de conexión Psycopg2
def dbConnect (db_parm, username_parm, host_parm, pw_parm):
# Parse in connection information
credentials = {'host': host_parm, 'database': db_parm, 'user': username_parm, 'password': pw_parm}
conn = psycopg2.connect(**credentials)
conn.autocommit = True # auto-commit each entry to the database
conn.cursor_factory = RealDictCursor
cur = conn.cursor()
print ("Connected Successfully to DB: " + str(db_parm) + "@" + str(host_parm))
return conn, cur
Conectarse a la base de datos
conn, cur = dbConnect(databaseName, dbUser, dbHost, dbPwd)
Suponiendo que el marco de datos ya esté presente como df
output = io.BytesIO() # For Python3 use StringIO
df.to_csv(output, sep='\t', header=True, index=False)
output.seek(0) # Required for rewinding the String object
copy_query = "COPY mem_info FROM STDOUT csv DELIMITER '\t' NULL '' ESCAPE '\\' HEADER " # Replace your table name in place of mem_info
cur.copy_expert(copy_query, output)
conn.commit()