2011-03-11 71 views
3

任何人對生活在關係數據庫中的數據進行非常基本的統計研究都必須計算交叉表,也稱爲應急表(wikipedia page)。當您需要統計同時有多少物品落在多個類別時,這些是不可或缺的。例如:有多少顧客是女性,喜歡巧克力?使用Python ORM的交叉表(列聯表)

Scipy有方法使用histogram2d的變體對矩陣執行此操作。但對於有意義的統計分析,您需要能夠有一個表(帶有變量名稱),從中可以指定要列表的變量。而且,它需要適用於其他類型的變量,而不僅僅是數字。實際上,數字製表是比較複雜的,因爲它需要裝箱。 R自然有這樣的功能,稱爲table,它可以很容易地移植到Python。不過,請記住我在標題中提到我想使用ORM,爲什麼?由於交叉表比用於生成數據的數據小得多,並且您可以從數據庫中的數十億記錄中計算出2x2表。我的觀點是:在嚴肅的應用程序中,您無法將所有數據都帶入內存並循環訪問。所以你必須把表格設計轉換成一個SQL查詢,這樣所有的計數都將由數據庫引擎完成。 ORM將負責必要的SQL方言調整,以便您可以在任何數據庫後端運行代碼。 一個簡單交叉列表的SQL(用MySQL方言)的例子可以找到here

所以現在我想我已經激發了你對這個問題的興趣,下面是問題:這個功能是否在任何Python ORM中實現?你將如何使用SQLAlchemy或Django ORM來實現這一點?

回答

2

我討厭回答我自己的問題,但有時我們不能等待幫助。而且,既然我找到了答案,並且很好,我覺得有責任與社區分享。所以這裏是:

table = self.session.query(Table.var1, Table.var2, func.count(Table)).group_by(Table.var1, Table.var2).all() 

這將返回像(行,列,計數)的元組列表。從這個列表中,您可以組裝您的應急表並根據需要計算保證金總計。值得一提的是,計算這條電纜的時間爲.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)