SQLAlchemy ORM-Konvertierung in Pandas DataFrame

106

Dieses Thema wurde seit einiger Zeit weder hier noch anderswo angesprochen. Gibt es eine Lösung, die eine SQLAlchemy <Query object>in einen Pandas DataFrame konvertiert?

Pandas kann verwendet werden pandas.read_sql, dies erfordert jedoch die Verwendung von unformatiertem SQL. Ich habe zwei Gründe, dies vermeiden zu wollen: 1) Ich habe bereits alles mit dem ORM (ein guter Grund für sich) und 2) Ich verwende Python-Listen als Teil der Abfrage (z. B. .db.session.query(Item).filter(Item.symbol.in_(add_symbols)wo Itemist meine Modellklasse? und add_symbolsist eine Liste). Dies entspricht SQL SELECT ... from ... WHERE ... IN.

Ist alles möglich?

Jared
quelle

Antworten:

191

Unten sollte in den meisten Fällen funktionieren:

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

pandas.read_sqlWeitere Informationen zu den Parametern finden Sie in der Dokumentation.

van
quelle
@van +1 könnte aber etwas detaillierter sein. zB habe ich df = pd.read_sql(query, query.bind)wann queryist a sqlalchemy.sql.selectable.Select. Ansonsten habe ich 'Select' object has no attribute 'session'.
Little Bobby Tables
Zum Kopieren und Einfügen habe ich einen Link zur Dokumentation direkt in der Antwort hinzugefügt, der Ihre Frage abdeckt: Sie sollten den conParameter angeben, der der engineorconnection string
van
@van Wäre es besser, hier query.session.connection () zu verwenden? Andernfalls berücksichtigt die Abfrage nicht vorhandene Änderungen in der Sitzung nicht ...
Datenfluss
1
@dataflow: Ich denke du hast recht, aber ich habe die Annahme nie getestet.
van
@van - dies löst 'TypeError: Sequenzelement 0: erwartete Zeichenfolge, DefaultMeta gefunden' aus; Ich habe mir den ganzen Tag die Haare ausgerissen, um herauszufinden, was los ist. Ich kann mir nur vorstellen, dass es etwas damit zu tun haben könnte, eine Verbindung aus einer scoped_session zu extrahieren ...
andrewpederson
84

Um dies für unerfahrene Pandas-Programmierer klarer zu machen, hier ein konkretes Beispiel:

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

Hier wählen wir eine Beschwerde aus der Beschwerde-Tabelle (sqlalchemy-Modell ist Beschwerde) mit id = 2 aus

Chandan Purohit
quelle
1
Ich denke, das ist klarer, wenn der Code ORM-basiert ist.
user40780
OH MEIN GOTT! Ich hatte viel mit der Hölle von sqlAlchemy zu kämpfen. Nur eine Randnotiz hier: Sie können auch read_sql schreiben ('SELECT * FROM TABLENAME', db.session.bind). Vielen Dank. Die obige Antwort hat mir mehr geholfen als die akzeptierte.
PallavBakshi
3
Was macht .statementdas
Kardamom
4
@cardamom gibt die SQL-Abfrage zurück.
Nuno André
10

Die ausgewählte Lösung hat bei mir nicht funktioniert, da ich immer wieder den Fehler bekam

AttributeError: Das Objekt 'AnnotatedSelect' hat kein Attribut 'lower'.

Ich fand folgendes funktioniert:

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

Wenn Sie eine Abfrage mit Parametern und dialektspezifischen Argumenten kompilieren möchten, verwenden Sie Folgendes:

c = query.statement.compile(query.session.bind)
df = pandas.read_sql(c.string, query.session.bind, params=c.params)
Johan Dahlin
quelle
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
quelle
Der Import von selectin df_query = select([DailyTrendsTable])fehlt. from sqlalchemy import select
Carlos Azevedo