Conversion de SQLAlchemy ORM en pandas DataFrame


107

Ce sujet n'a pas été abordé depuis un moment, ici ou ailleurs. Existe-t-il une solution pour convertir un SQLAlchemy <Query object>en un pandas DataFrame?

Pandas a la capacité d'utiliser pandas.read_sqlmais cela nécessite l'utilisation de SQL brut. J'ai deux raisons de vouloir l'éviter: 1) J'ai déjà tout utilisant l'ORM (une bonne raison en soi) et 2) J'utilise des listes python dans le cadre de la requête (par exemple: .db.session.query(Item).filter(Item.symbol.in_(add_symbols)Itemest ma classe de modèle et add_symbolsest une liste). C'est l'équivalent de SQL SELECT ... from ... WHERE ... IN.

Est-ce que quelque chose est possible?

Réponses:


192

Ci-dessous devrait fonctionner dans la plupart des cas:

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

Consultez la pandas.read_sqldocumentation pour plus d'informations sur les paramètres.


@van +1 mais pourrait faire avec un peu plus de détails. par exemple je l'ai fait df = pd.read_sql(query, query.bind)quand queryest un sqlalchemy.sql.selectable.Select. Sinon, je l'ai 'Select' object has no attribute 'session'.
Little Bobby Tables

Afin de copier-coller, j'ai ajouté un lien vers la documentation directement dans la réponse, qui couvre votre question: vous devez fournir le conparamètre, qui peut être le engineouconnection string
van

@van Serait-il préférable d'utiliser ici query.session.connection ()? Sinon, la requête ne prend pas en compte les changements non persistants dans la session ...
dataflow

1
@dataflow: Je pense que vous avez raison, mais je n'ai jamais testé l'hypothèse.
van

@van - cela lance 'TypeError: élément de séquence 0: chaîne attendue, DefaultMeta trouvée'; Je me suis arraché les cheveux toute la journée pour essayer de comprendre ce qui ne va pas La seule chose que je peux comprendre, c'est que cela pourrait avoir quelque chose à voir avec la tentative d'extraire une connexion d'une scoped_session ....
andrewpederson

86

Juste pour rendre cela plus clair pour les programmeurs pandas novices, voici un exemple concret,

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

Ici, nous sélectionnons une plainte dans la table des plaintes (le modèle sqlalchemy est une plainte) avec id = 2


1
Je pense que c'est plus clair, lorsque le code est basé sur ORM.
user40780

OMG! J'ai beaucoup lutté avec sqlAlchemy hell. Juste un petit mot ici: vous pouvez également écrire read_sql ('SELECT * FROM TABLENAME', db.session.bind). Merci. La réponse ci-dessus m'a aidé plus que la réponse acceptée.
PallavBakshi

3
Que fait .statement-on?
cardamome

4
@cardamom il renvoie la requête SQL.
Nuno André

10

La solution sélectionnée n'a pas fonctionné pour moi, car je continuais à recevoir l'erreur

AttributeError: l'objet 'AnnotatedSelect' n'a pas d'attribut 'lower'

J'ai trouvé ce qui suit fonctionné:

df = pd.read_sql_query(query.statement, engine)

4

Si vous souhaitez compiler une requête avec des paramètres et des arguments spécifiques au dialecte, utilisez quelque chose comme ceci:

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)

L'importation de selectin df_query = select([DailyTrendsTable])est manquante. from sqlalchemy import select
Carlos Azevedo
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.