Réponses:
À partir de pandas 0.14 (publié fin mai 2014), postgresql est pris en charge. Le sql
module utilise maintenant sqlalchemy
pour prendre en charge différentes saveurs de base de données. Vous pouvez transmettre un moteur sqlalchemy pour une base de données postgresql (voir la documentation ). Par exemple:
from sqlalchemy import create_engine
engine = create_engine('postgresql://scott:tiger@localhost:5432/mydatabase')
df.to_sql('table_name', engine)
Vous avez raison de dire que dans les pandas jusqu'à la version 0.13.1, postgresql n'était pas pris en charge. Si vous devez utiliser une version plus ancienne de pandas, voici une version corrigée de pandas.io.sql
: https://gist.github.com/jorisvandenbossche/10841234 .
Je l'ai écrit il y a un certain temps, je ne peux donc pas garantir pleinement que cela fonctionne toujours, mais la base devrait être là). Si vous placez ce fichier dans votre répertoire de travail et que vous l'importez, vous devriez pouvoir faire (où se con
trouve une connexion postgresql):
import sql # the patched version (file is named sql.py)
sql.write_frame(df, 'table_name', con, flavor='postgresql')
Sqlalchemy engine
, puis-je utiliser une Postgres
connexion existante créée à l'aide de psycopg2.connect()
?
Option plus rapide:
Le code suivant copiera votre Pandas DF vers postgres DB beaucoup plus rapidement que la méthode df.to_sql et vous n'aurez pas besoin d'un fichier csv intermédiaire pour stocker le df.
Créez un moteur basé sur vos spécifications DB.
Créez une table dans votre base de données postgres qui a le même nombre de colonnes que le Dataframe (df).
Les données dans DF seront insérées dans votre table postgres.
from sqlalchemy import create_engine
import psycopg2
import io
si vous souhaitez remplacer la table, nous pouvons la remplacer par la méthode to_sql normale en utilisant les en-têtes de notre df, puis charger tout le df qui prend beaucoup de temps dans 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
? Cela devrait-il être celui qui est écrit copy_from()
?
contents
variable, tout le reste devrait bien fonctionner
output.seek(0)
?
Solution Pandas 0.24.0+
Dans Pandas 0.24.0, une nouvelle fonctionnalité a été introduite spécialement conçue pour les écritures rapides sur Postgres. Vous pouvez en savoir plus ici: 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'
option d' ajout est assez rapide. Mais oui, cette COPY
méthode est actuellement la méthode la plus rapide.
with
écriture dans une mémoire tampon. La dernière partie de l ' with
utilise une instruction SQL et profite de la vitesse de copy_expert pour charger les données en masse. Quelle est la partie médiane qui commence par columns =
faire?
keys
arguments de la psql_insert_copy
fonction s'il vous plaît? Comment obtient-il des clés et les clés sont-elles uniquement les noms de colonnes?
Table 'XYZ' already exists
. Pour autant que je sache, cela ne devrait pas créer une table, n'est-ce pas?
df.to_sql('table_name', engine, if_exists='replace', method=psql_insert_copy)
- cela crée une table dans votre base de données.
Voilà comment je l'ai fait.
Cela peut être plus rapide car il utilise 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()
Pour Python 2.7 et Pandas 0.24.2 et utilisant Psycopg2
Module de connexion 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
Connectez-vous à la base de données
conn, cur = dbConnect(databaseName, dbUser, dbHost, dbPwd)
En supposant que le dataframe soit déjà présent en tant que 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()