web-dev-qa-db-ja.com

DataFrameをpostgresテーブルに書き込む方法は?

DataFrame.to_sqlメソッドがありますが、mysql、sqlite、およびOracleデータベースでのみ機能します。このメソッドにpostgres接続またはsqlalchemyエンジンを渡すことはできません。

65
m9_psy

pandas 0.14(2014年5月末にリリース)以降、postgresqlがサポートされます。 sqlモジュールはsqlalchemyを使用して、さまざまなデータベースフレーバーをサポートするようになりました。 postgresqlデータベースにsqlalchemyエンジンを渡すことができます( docs を参照)。例えば。:

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

あなたはpandasバージョン0.13.1までpostgresqlがサポートされていなかったことは正しいです。古いバージョンのパンダを使用する必要がある場合、パッチを適用したpandas.io.sqlのバージョンは次のとおりです。 https://Gist.github.com/jorisvandenbossche/10841234
これは少し前に書いたので、常に機能することを完全に保証することはできませんが、基礎はそこにあるべきです)。そのファイルを作業ディレクトリに置いてインポートすると、次のことができるはずです(conはpostgresql接続です):

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

高速オプション:

次のコードは、Pandas DFをdf.to_sqlメソッドよりもはるかに高速にpostgres DBにコピーし、dfを保存するための中間のcsvファイルは必要ありません。

DB仕様に基づいてエンジンを作成します。

データフレーム(df)と同じ列数を持つテーブルをpostgres DBに作成します。

DFのデータは、postgresテーブルにinsertedを取得します。

from sqlalchemy import create_engine
import psycopg2 
import io

テーブルを置き換える場合は、dfのヘッダーを使用して通常のto_sqlメソッドに置き換えてから、時間のかかるdf全体を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()
53
Aseem

これは私がそれを行う方法です、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

パンダ0.24.0+ソリューション

Pandas 0.24.0では、Postgresへの高速書き込み用に特別に設計された新しい機能が導入されました。詳細についてはこちらをご覧ください: 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)
8
mgoldwasser