Konversi SQLAlchemy ORM ke DataFrame pandas

107

Topik ini sudah lama tidak dibahas, di sini atau di tempat lain. Apakah ada solusi untuk mengonversi SQLAlchemy <Query object>menjadi DataFrame pandas?

Panda memiliki kemampuan untuk digunakan, pandas.read_sqltetapi ini membutuhkan penggunaan SQL mentah. Saya memiliki dua alasan untuk menghindarinya: 1) Saya sudah memiliki segalanya menggunakan ORM (alasan yang bagus dalam dan dari dirinya sendiri) dan 2) Saya menggunakan daftar python sebagai bagian dari kueri (misalnya: di .db.session.query(Item).filter(Item.symbol.in_(add_symbols)mana Itemkelas model saya dan add_symbolsdaftar). Ini sama dengan SQL SELECT ... from ... WHERE ... IN.

Apakah ada yang mungkin?

Jared
sumber

Jawaban:

192

Di bawah ini seharusnya berfungsi dalam banyak kasus:

df = pd.read_sql(query.statement, query.session.bind)

Lihat pandas.read_sqldokumentasi untuk informasi lebih lanjut tentang parameter.

mobil van
sumber
@van +1 tetapi dapat dilakukan dengan sedikit lebih detail. misalnya saya lakukan df = pd.read_sql(query, query.bind)kapan queryadalah sqlalchemy.sql.selectable.Select. Kalau tidak, saya mengerti 'Select' object has no attribute 'session'.
Little Bobby Tables
Untuk menyalin-tempel, saya menambahkan tautan ke dokumentasi langsung di jawaban, yang mencakup pertanyaan Anda: Anda harus memberikan conparameter, yang dapat berupa engineorconnection string
van
@ Van Apakah lebih baik menggunakan query.session.connection () di sini? Jika tidak, kueri tidak memperhitungkan perubahan tak terpisahkan dalam sesi ...
dataflow
1
@ Dataflow: Saya pikir Anda benar, tetapi saya tidak pernah menguji asumsi tersebut.
van
@van - ini melempar 'TypeError: urutan item 0: string yang diharapkan, DefaultMeta ditemukan'; merobek rambutku sepanjang hari mencoba mencari tahu apa yang salah. Satu-satunya hal yang dapat saya pikirkan adalah bahwa itu mungkin ada hubungannya dengan mencoba mengekstrak koneksi dari scoped_session ....
andrewpederson
86

Untuk memperjelas hal ini bagi pemrogram panda pemula, berikut adalah contoh konkretnya,

pd.read_sql(session.query(Complaint).filter(Complaint.id == 2).statement,session.bind) 

Di sini kami memilih keluhan dari tabel keluhan (model sqlalchemy adalah Keluhan) dengan id = 2

Chandan Purohit
sumber
1
Saya rasa ini lebih jelas, ketika kodenya berbasis ORM.
pengguna40780
OH TUHAN! Saya sering berjuang dengan sqlAlchemy hell. Sekadar catatan tambahan di sini: Anda juga dapat menulis read_sql ('SELECT * FROM TABLENAME', db.session.bind). Terima kasih. Jawaban di atas membantu saya lebih dari yang diterima.
PallavBakshi
3
Apa yang .statementdilakukannya?
kapulaga
4
@cardamom ini mengembalikan kueri sql.
Nuno André
10

Solusi yang dipilih tidak berhasil untuk saya, karena saya terus mendapatkan kesalahan

AttributeError: Objek 'AnnotatedSelect' tidak memiliki atribut 'lower'

Saya menemukan yang berikut berhasil:

df = pd.read_sql_query(query.statement, engine)
jorr45.dll
sumber
4

Jika Anda ingin mengompilasi kueri dengan parameter dan argumen khusus dialek, gunakan sesuatu seperti ini:

c = query.statement.compile(query.session.bind)
df = pandas.read_sql(c.string, query.session.bind, params=c.params)
Johan Dahlin
sumber
3
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

engine = create_engine('postgresql://postgres:postgres@localhost:5432/DB', echo=False)
Base = declarative_base(bind=engine)
Session = sessionmaker(bind=engine)
session = Session()

conn = session.bind

class DailyTrendsTable(Base):

    __tablename__ = 'trends'
    __table_args__ = ({"schema": 'mf_analysis'})

    company_code = Column(DOUBLE_PRECISION, primary_key=True)
    rt_bullish_trending = Column(Integer)
    rt_bearish_trending = Column(Integer)
    rt_bullish_non_trending = Column(Integer)
    rt_bearish_non_trending = Column(Integer)
    gen_date = Column(Date, primary_key=True)

df_query = select([DailyTrendsTable])

df_data = pd.read_sql(rt_daily_query, con = conn)
Akshay Salvi
sumber
Impor selectdalam df_query = select([DailyTrendsTable])hilang. from sqlalchemy import select
Carlos Azevedo