DataFrame.to_sql metodu var ama sadece mysql, sqlite ve oracle veritabanları için çalışıyor. Bu yönteme postgres bağlantı veya sqlalchemy motoruna geçemiyorum.
Yanıtlar:
Pandalar 0.14'ten başlayarak (Mayıs 2014 sonunda piyasaya sürüldü) postgresql desteklenmektedir. sql
Modül şimdi kullandığı sqlalchemy
farklı veritabanı tatlar destekleyecek. Postgresql veritabanı için bir sqlalchemy motorunu geçebilirsiniz ( belgelere bakın ). Örneğin:
from sqlalchemy import create_engine
engine = create_engine('postgresql://scott:tiger@localhost:5432/mydatabase')
df.to_sql('table_name', engine)
0.13.1 postgresql sürümüne kadar olan pandalarda desteklenmediğini doğru söylüyorsunuz. Pandaların daha eski bir sürümünü kullanmanız gerekiyorsa, şuranın yamalı sürümünü burada bulabilirsiniz pandas.io.sql
: https://gist.github.com/jorisvandenbossche/10841234 .
Bunu bir süre önce yazdım, bu yüzden her zaman işe yarayacağını tam olarak garanti edemem, ama temel orada olmalı). Bu dosyayı çalışma dizininize koyup içe aktarırsanız, şunları yapabilmeniz gerekir ( con
postgresql bağlantısı nerede ):
import sql # the patched version (file is named sql.py)
sql.write_frame(df, 'table_name', con, flavor='postgresql')
Sqlalchemy engine
bir Postgres
bağlantı oluşturmak yerine, kullanılarak oluşturulmuş mevcut bir bağlantıyı kullanabilir miyim psycopg2.connect()
?
Daha hızlı seçenek:
Aşağıdaki kod, Pandas DF'nizi postgres DB'ye df.to_sql yönteminden çok daha hızlı kopyalayacaktır ve df'yi depolamak için herhangi bir ara csv dosyasına ihtiyacınız olmayacaktır.
DB spesifikasyonlarınıza göre bir motor oluşturun.
Postgres DB'nizde Dataframe (df) ile eşit sayıda sütuna sahip bir tablo oluşturun.
DF'deki veriler postgres tablonuza eklenecektir .
from sqlalchemy import create_engine
import psycopg2
import io
tabloyu değiştirmek isterseniz, onu normal to_sql metodu ile değiştirebiliriz ve df'deki başlıkları kullanarak büyük zaman alan df'yi DB'ye yükleyebiliriz.
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
? Yazılan bu olmalı mı copy_from()
?
output.seek(0)
?
Pandas 0.24.0+ çözümü
Pandas 0.24.0'da, Postgres'e hızlı yazma için özel olarak tasarlanmış yeni bir özellik sunuldu. Buradan daha fazla bilgi edinebilirsiniz: 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'
seçeneği yeterince hızlıdır. Ama evet, bu COPY
yöntem şu anda en hızlı yoldur.
with
bir ara belleğe yazmaktır. Son kısmı, with
bir SQL ifadesi kullanmak ve verileri toplu olarak yüklemek için copy_expert'in hızından yararlanmaktır. Yapmakla başlayan orta kısım nedir columns =
?
keys
argümanları açıklar psql_insert_copy
mısınız lütfen? Anahtarları nasıl alıyor ve anahtarlar sadece sütun adları mı?
Table 'XYZ' already exists
. Anladığım kadarıyla bir tablo oluşturmamalı, değil mi?
df.to_sql('table_name', engine, if_exists='replace', method=psql_insert_copy)
- bu, veritabanınızda bir tablo oluşturur.
Ben böyle yaptım.
Daha hızlı olabilir çünkü şunları kullanıyor 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()
Python 2.7 ve Pandas 0.24.2 için ve Psycopg2 kullanımı
Psycopg2 Bağlantı Modülü
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
Veritabanına bağlanın
conn, cur = dbConnect(databaseName, dbUser, dbHost, dbPwd)
Veri çerçevesinin zaten df olarak mevcut olduğunu varsayarsak
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()