使用Python ORM的交叉表(列联表)?
Posted
技术标签:
【中文标题】使用Python ORM的交叉表(列联表)?【英文标题】:Cross-tabulation (contingency table) using Python ORM? 【发布时间】:2011-03-11 13:21:06 【问题描述】:任何对关系数据库中的数据进行非常基本的统计探索的人都必须计算交叉表,也称为列联表 (wikipedia page)。当您需要计算有多少项目同时属于多个类别时,这些是必不可少的。例如:有多少顾客是女性并且喜欢巧克力?
Scipy 可以使用 histogram2d 的变体对矩阵执行此操作,但是对于有意义的统计分析,您需要能够有一个表格(带有变量名称),您可以从中指定您想要制表的变量。此外,它需要适用于其他类型的变量,而不仅仅是数字。实际上,数字制表是更复杂的一种,因为它需要分箱。 R
自然有这样一个函数,叫做table
,可以很容易地移植到 Python 中。但是,记得我在标题中提到我想使用 ORM,为什么?因为交叉表比用于生成它的数据要小得多,而且您可以拥有一个从数据库上的数十亿条记录中计算出来的 2x2 表。我的观点是:在严肃的应用程序中,您无法将所有数据都放入内存并循环访问它。因此,您必须将表设计转换为 SQL 查询,以便所有计数都由数据库引擎完成。 ORM 将负责必要的 SQL 方言调整,以便您可以使用任何数据库后端运行您的代码。
可以在here 找到一个用于简单交叉表的 SQL(mysql 方言)示例。
既然我想我已经激发了你对这个问题的兴趣,这里有一些问题:这个功能是否在任何 Python ORM 中实现?你将如何使用 SQLAlchemy 或 Django ORM 来实现这一点?
【问题讨论】:
【参考方案1】:我不想回答我自己的问题,但有时我们迫不及待地寻求帮助。既然我找到了答案并且是一个好的答案,我觉得有义务与社区分享。所以这里是:
table = self.session.query(Table.var1, Table.var2, func.count(Table)).group_by(Table.var1, Table.var2).all()
这将返回一个元组列表,如 (row,column,count)。从此列表中,您可以根据需要组装您的列联表并计算保证金总额。值得一提的是,对于具有 296110 条记录的表,计算这条电缆需要 .28 秒,而 var1 和 var2 分别有 5 和 90 级。
现在有一个小函数来组装和打印 (2d) 表:
def pprint_table():
colnames = list(set([i[1] for i in table]))
rows = defaultdict(lambda:[0]*len(colnames))
for r in table:
rows[r[0]][colnames.index(r[1])] = r[2]
print colnames, 'total'
for rn, r in rows.items():
print rn, r, sum(r)
【讨论】:
以上是关于使用Python ORM的交叉表(列联表)?的主要内容,如果未能解决你的问题,请参考以下文章