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?

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 +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


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)

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)

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)

Der Import von selectin df_query = select([DailyTrendsTable])fehlt. from sqlalchemy import select
Carlos Azevedo
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.