web-dev-qa-db-fra.com

Comment écrire DataFrame sur la table postgres?

Il existe une méthode DataFrame.to_sql, mais elle ne fonctionne que pour les bases de données mysql, sqlite et Oracle. Je ne peux pas passer à cette méthode postgres connection ou sqlalchemy engine.

65
m9_psy

Postgresql est pris en charge à partir de pandas 0.14 (publié fin mai 2014). Le module sql utilise désormais sqlalchemy pour prendre en charge différents types de bases de données. Vous pouvez passer un moteur sqlalchemy pour une base de données postgresql (voir docs ).

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 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 ya quelque temps, je ne peux donc pas garantir que cela fonctionne toujours, mais la base devrait être là). Si vous mettez ce fichier dans votre répertoire de travail et l'importez, vous devriez pouvoir le faire (où con est une connexion postgresql):

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

Option plus rapide:

Le code suivant va copier votre Pandas DF dans une base de données postgres beaucoup plus rapide que la méthode df.to_sql et vous n'aurez besoin d'aucun fichier csv intermédiaire pour stocker le fichier df. .

Créez un moteur basé sur vos spécifications de base de données.

Créez une table dans votre base de données postgres comportant un nombre de colonnes égal à celui du 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 fichier df, puis charger le fichier df, qui prend beaucoup de temps et qui prend beaucoup de temps.

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()
53
Aseem

Voici comment je le fais, je peux ê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()
    cur = db_conn.cursor()
    psycopg2.extras.execute_batch(cur, insert_stmt, df.values)
    conn.commit()
    cur.close()
9
Behdad Forghani

Solution Pandas 0.24.0+

Dans Pandas 0.24.0, une nouvelle fonctionnalité spécialement conçue pour les écritures rapides dans Postgres a été introduite. Vous pouvez en apprendre plus à ce sujet ici: https://pandas.pydata.org/pandas -docs/stable/user_guide/io.html # méthode io-sql

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)
8
mgoldwasser