Python 在写入dataframe之前,在SqlAlchemy中设置列的顺序

Python 在写入dataframe之前,在SqlAlchemy中设置列的顺序,python,pandas,sqlalchemy,pyodbc,Python,Pandas,Sqlalchemy,Pyodbc,在使用SQLAlchemy构建表时,我正在尝试设置列的顺序,到目前为止,列是按字母顺序出现的,我目前有: def data_frame(query, columns): def make_row(x): return dict([(c, getattr(x, c)) for c in columns]) return pd.DataFrame([make_row(x) for x in query]) PackL = create_engine('mssql+

在使用SQLAlchemy构建表时,我正在尝试设置列的顺序,到目前为止,列是按字母顺序出现的,我目前有:

def data_frame(query, columns):
    def make_row(x):
        return dict([(c, getattr(x, c)) for c in columns]) 
    return pd.DataFrame([make_row(x) for x in query])

PackL = create_engine('mssql+pyodbc://u:pass@Server/db1?driver=SQL Server', echo=False)
Fabr = create_engine('mssql+pyodbc://u:pass@Server/db2?driver=SQL Server', echo=False)
Session = sessionmaker(bind=PackL)
session = Session()
Base = declarative_base()
metadata = MetaData()

class Tranv(Base):
    __tablename__= "Transactions"
    __table_args__= {'autoload': True, 'autoload_with':PackL}

newvarv = session.query(Tranv).filter_by(status='SCRAP').filter(Tranv.time_stamp.
between('2015-10-01', '2015-10-09'))

session.close()

dfx = data_frame(newvarv, ['action', 'employee_number', 'time_stamp', 'qty', 
'part_number', 'card_number'])
当前的dfx具有按字母顺序排列的列,但我希望它按照我在创建数据帧dfx时定义列的顺序排列。因此,订单将是操作、员工编号、时间戳、数量、零件编号、卡号。我可以很容易地用熊猫做到这一点,但这似乎是额外的(和不必要的)步骤


我搜索了文档、google和stackoverflow,但似乎没有任何东西真正符合我的需要。由于我对SQLAlchemy还不熟悉,我非常感谢您的帮助。我是否认为因为我正在自动加载表,所以无法轻松定义列的顺序(我确信有一个解决方法,但不知道文档中可能找到的位置)

列不符合指定顺序的原因与sql查询或sqlalchemy无关。这是因为您将查询输出转换为字典,然后将字典馈送到
DataFrame

由于python中字典没有顺序,pandas将按字母顺序对其进行排序,以获得可预测的输出

使用dict的当前方法,您始终可以通过执行
dfx.reindex(columns=['action',…,'card\u number'])来更改列的顺序。


除了解释为什么在您的案例中没有订购外,可能还有更好的解决方法:

  • 使用内置的
    pd.read\u sql\u查询
    。使用会话和查询对象时,您可以将
    selectable
    属性传递到
    read\u sql\u Query
    以将其转换为数据帧:

    query = session.query(Table)...
    df = pd.read_sql_query(query.selectable, engine)
    
  • 不要转换为字典,而是将输出保留为元组,并将元组馈送到
    DataFrame
    :这将保持查询输出的顺序

我认为您也可以使用
dfx=pd.read\u sql\u query(newvarv,PackL)
将查询转换为数据帧,而无需编写您自己的方法(但不完全确定)。要对我自己的评论进行评论,您需要传递
newvarv.selective
,请参阅我的更新答案。谢谢,这很有意义;没有考虑查询输出转换。我以前尝试过pd.read\u sql\u查询(事实上,我取出了我的data\u frame函数并用您之前的注释替换了它),但我总是遇到以下错误:sqlalchemy.exc.InvalidRequestError:不可执行的对象类型:是的,抱歉,您是正确的。但是,您可以传递查询对象的
selectable
属性:
pd.read\u sql\u Query(Query.selectable,engine)
。这样,您不需要自己编写的方法来将其转换为数据帧。谢谢,这可能是最简单的解决方案,当然比我以前所做的更容易实现。