如何将DataFrame写入postgres表?


103

DataFrame.to_sql方法,但仅适用于mysql,sqlite和oracle数据库。我无法传递给此方法postgres连接或sqlalchemy引擎。

Answers:


125

从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)

您是正确的,在不支持0.13.1版本的熊猫中,不支持postgresql。如果您需要使用旧版本的熊猫,请使用以下修补版本pandas.io.sqlhttps : //gist.github.com/jorisvandenbossche/10841234
我是在前一段时间写的,所以不能完全保证它始终有效,但是基础应该在那里)。如果将该文件放在工作目录中并导入,那么您应该能够执行此操作(conPostgreSQL连接在哪里):

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

1
这是否达到0.14?
2014年

是的,并且已经发布了0.15(候选发布)。我将更新答案,谢谢提问。
joris 2014年

1
这篇文章为我解决了这个问题:stackoverflow.com/questions/24189150/…–
srodriguex

注意:to_sql不会在postgres中导出数组类型。
Saurabh Saha19年

1
Sqlalchemy engine我可以使用Postgres创建的现有连接代替创建新的连接psycopg2.connect()吗?
贾维斯

84

更快的选择:

以下代码比df.to_sql方法将您的Pandas DF复制到postgres DB的速度要快得多,并且您不需要任何中间的csv文件来存储df。

根据数据库规范创建引擎。

在您的postgres DB中创建一个表,该表的列数与Dataframe(df)相同。

DF中的数据将插入到您的postgres表中。

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

变量有contents什么作用?这应该是写的copy_from()吗?
n1000

@ N1000呀忽略的contents变量,一切应该只是罚款
巴比

2
你为什么output.seek(0)呢?
moshevi

7
这是如此之快以至于很有趣:D
shadi

1
由于某些字段中有换行符,因此表加载失败。我该如何处理?df.to_csv(output,sep ='\ t',header = False,index = False,encoding ='utf-8')cur.copy_from(output,'messages',null =“”)#空值变为''
conetfun

23

熊猫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)

3
在大多数情况下,添加method='multi'选项足够快。但是,是的,这种COPY方法是目前最快的方法。
ssword,

这是仅用于csv吗?可以与.xlsx一起使用吗?关于此操作的每个部分的一些说明将很有帮助。之后的第一部分with正在写入内存缓冲区。的最后一部分with使用SQL语句,并利用copy_expert的速度批量加载数据。首先要做的中间部分是columns =什么?
DudeWah

这对我来说非常有效。您能解释一下keys函数中的参数psql_insert_copy吗?它如何获取任何键,并且这些键仅仅是列名?
刘宝文

我尝试使用此方法,但是会引发错误:Table 'XYZ' already exists。据我了解,它不应该创建表,对吗?
E. Epstein

@Epstein-您可以将最后一行修改为df.to_sql('table_name', engine, if_exists='replace', method=psql_insert_copy)-这确实会在数据库中创建一个表。
mgoldwasser

21

这就是我做的。

可能更快,因为它正在使用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()

1
我得到AttributeError:模块'psycopg2'没有属性'extras'。嗯,这需要显式导入。进口psycopg2.extras
GeorgeLPerkins 19-4-22

此功能比sqlalchemy解决方案快得多
Saurabh Saha

-1

对于Python 2.7和Pandas 0.24.2并使用Psycopg2

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

连接到数据库

conn, cur = dbConnect(databaseName, dbUser, dbHost, dbPwd)

假设数据帧已经作为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()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.