转向SQLAlchemy

fri*_*kit 1 python sql pivot sqlalchemy

想象一下按日期和名称键入的表主键.

|Date|Name|Value|
|D1  |   A|    2|
|D1  |   B|    3|
|D2  |   A|    3|
|D2  |   C|    1|
Run Code Online (Sandbox Code Playgroud)

如何编写一个SQLAlchemy查询,产生(日期,值)对,其中值是该日期所有名称的所有值?值元组的长度将是,len(distinct(Name))并且缺失值将包含一些标记值(例如,无).

i.e.
[
(D1, 2, 3, None),
(D2, 3, None, 1),
...
]
Run Code Online (Sandbox Code Playgroud)

我不是要在这里要求一个完整的答案,以便让我批准.如果您可以告诉我在文档中搜索/阅读哪些概念(或者真的,请指出任何有用或相关的内容),我会(尝试)自己弄清楚并发布更新.

[请不要大熊猫解决方案]

简单的答案是以长格式加载查询并使用numpy.searchsorted在numpy中进行透视,但如果提交的答案使用了这个,我会对一些性能诊断感兴趣,以便与简单的解决方案进行比较.

van*_*van 5

SQL Server除非你有大量的数据,否则我建议不要这样做(即使在这种情况下,我也不确定它是否会产生显着的正面性能影响).

相反,使用他们擅长的不同工具:

  • MS-SQL (或其他RDBMS)来存储数据
  • SQLAlchemy 插入/查询该数据
  • numpy例程或pandas.pivot转动数据

下面的代码是自包含的,运行(带sqlite)并显示如何获得您想要的最终结果:

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
import pandas as pd

_db_uri = 'sqlite:///:memory:'
engine = create_engine(_db_uri, echo=True)
Session = sessionmaker(bind=engine)

Base = declarative_base(engine)

class MyTable(Base):
    __tablename__ = 'my_table'
    id = Column(Integer, primary_key=True)
    date = Column(String)
    name = Column(String)
    value = Column(Integer)

def _test():
    Base.metadata.drop_all(engine)
    Base.metadata.create_all(engine)
    session = Session()

    def _add_test_data():
        rows = [
            MyTable(date="D1", name="A", value=2),
            MyTable(date="D1", name="B", value=3),
            MyTable(date="D2", name="A", value=3),
            MyTable(date="D2", name="C", value=1),
        ]
        session.add_all(rows)
        session.commit()

    # create test data
    _add_test_data()

    # use `sa` to query data from the database
    # q = session.query(MyTable)  # all columns
    q = session.query(MyTable.date, MyTable.name, MyTable.value)  # explicit

    # read data into pandas directly from the query `q`
    df = pd.read_sql(q.statement, q.session.bind)
    print(df)

    # pivot the results
    df_pivot = df.pivot(index="date", columns="name", values="value")
    print(df_pivot)


if __name__ == '__main__':
    _test()
Run Code Online (Sandbox Code Playgroud)

  • 对不起,请不要熊猫。 (3认同)