Перетворення SQLAlchemy ORM в панди DataFrame


107

Цю тему певний час не обговорювали тут чи деінде. Чи є рішення, яке перетворює SQLAlchemy <Query object>на панду DataFrame?

Pandas має можливість використовувати, pandas.read_sqlале для цього потрібно використовувати необроблений SQL. У мене є дві причини, що хочу цього уникнути: 1) У мене вже є все, що використовує ORM (це є вагомою причиною саме по собі) і 2) я використовую списки python як частину запиту (наприклад: .db.session.query(Item).filter(Item.symbol.in_(add_symbols)де Itemмій клас моделі і add_symbolsє списком). Це еквівалент SQL SELECT ... from ... WHERE ... IN.

Чи можливо щось?

Відповіді:


192

Нижче має працювати в більшості випадків:

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

Додаткову pandas.read_sqlінформацію про параметри див. У документації.


@van +1, але можна зробити трохи детальніше. наприклад, я зробив, df = pd.read_sql(query, query.bind)коли queryє sqlalchemy.sql.selectable.Select. В іншому випадку я отримав 'Select' object has no attribute 'session'.
Столики маленького бобі

Щоб скопіювати вставку, я додав посилання на документацію безпосередньо у відповідь, яка охоплює ваше запитання: ви повинні вказати conпараметр, який може бути engineабоconnection string
van

@van Чи було б краще тут використовувати query.session.connection ()? Інакше запит не враховує нерозподілених змін у сеансі ...
потік даних

1
@dataflow: Я думаю, ти маєш рацію, але я ніколи не перевіряв припущення.
ван

@van - це кидає "TypeError: елемент послідовності 0: очікувана рядок, знайдено DefaultMeta"; цілий день виривав волосся, намагаючись зрозуміти, що не так. Єдине, що я можу зрозуміти, це те, що це може мати щось спільне зі спробою вилучити з'єднання з scoped_session ....
andrewpederson

86

Щоб зробити це більш зрозумілим для початківців програмістів панд, ось конкретний приклад,

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

Тут ми вибираємо скаргу із таблиці скарг (модель sqlalchemy - Скарга) з id = 2


1
Я думаю, що це зрозуміліше, коли код заснований на ORM.
user40780

О БОЖЕ МІЙ! Я багато боровся з пекелом sqlAlchemy. Тут є лише бічна примітка: Ви також можете написати read_sql ("SELECT * FROM TABLENAME", db.session.bind). Дякую. Наведена відповідь допомогла мені більше, ніж прийнята.
PallavBakshi

3
Що робить .statement?
кардамон

4
@cardamom він повертає запит sql.
Нуно Андре

10

Вибране рішення не працювало для мене, оскільки я постійно отримував помилку

AttributeError: Об'єкт 'AnnotatedSelect' не має атрибута 'нижній'

Я виявив, що працювали:

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

4

Якщо ви хочете скласти запит з параметрами та діалектні конкретні аргументи, використовуйте щось подібне:

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)

Відсутній імпорт selectв df_query = select([DailyTrendsTable]). from sqlalchemy import select
Карлос Азеведо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.