2012-07-11 88 views
5

我想要一種方式來總結一個數據庫表,以便共享一個公共ID的行彙總到一行輸出中。產生一個摘要(「pivot」?)表

我的工具是SQLite和Python 2.x.

例如,水果價格在我的本地超市下表給出...

+--------------------+--------------------+--------------------+ 
|Fruit    |Shop    |Price    | 
+--------------------+--------------------+--------------------+ 
|Apple    |Coles    |$1.50    | 
|Apple    |Woolworths   |$1.60    | 
|Apple    |IGA     |$1.70    | 
|Banana    |Coles    |$0.50    | 
|Banana    |Woolworths   |$0.60    | 
|Banana    |IGA     |$0.70    | 
|Cherry    |Coles    |$5.00    | 
|Date    |Coles    |$2.00    | 
|Date    |Woolworths   |$2.10    | 
|Elderberry   |IGA     |$10.00    | 
+--------------------+--------------------+--------------------+ 

...我想生產出我每個水果的價格在每個超市的彙總表。空格應該由NULL填充。

+----------+----------+----------+----------+ 
|Fruit  |Coles  |Woolworths|IGA  | 
+----------+----------+----------+----------+ 
|Apple  |$1.50  |$1.60  |$1.70  | 
|Banana |$0.50  |$0.60  |$0.70  | 
|Cherry |NULL  |$5.00  |NULL  | 
|Date  |$2.00  |$2.10  |NULL  | 
|Elderberry|NULL  |NULL  |$10.00 | 
+----------+----------+----------+----------+ 

我相信文學把這稱爲「數據透視表」或「轉動查詢」,但顯然SQLite doesn't support PIVOT.(在這個問題的解決方案使用硬編碼LEFT JOIN秒。這並不真正吸引我,因爲我不不知道「列」的名字提前。)

現在我通過遍歷Python中的整個表並積累dictdicts,這是有點klutzy這樣做。我願意提供更好的解決方案,無論是使用Python還是SQLite,它都會以表格形式提供數據。

回答

8

Python的一面,你可以使用一些魔法itertools爲重新安排你的數據:

data = [('Apple',  'Coles',  1.50), 
     ('Apple',  'Woolworths', 1.60), 
     ('Apple',  'IGA',  1.70), 
     ('Banana',  'Coles',  0.50), 
     ('Banana',  'Woolworths', 0.60), 
     ('Banana',  'IGA',  0.70), 
     ('Cherry',  'Coles',  5.00), 
     ('Date',  'Coles',  2.00), 
     ('Date',  'Woolworths', 2.10), 
     ('Elderberry', 'IGA',  10.00)] 

from itertools import groupby, islice 
from operator import itemgetter 
from collections import defaultdict 

stores = sorted(set(row[1] for row in data)) 
# probably splitting this up in multiple lines would be more readable 
pivot = ((fruit, defaultdict(lambda: None, (islice(d, 1, None) for d in data))) for fruit, data in groupby(sorted(data), itemgetter(0))) 

print 'Fruit'.ljust(12), '\t'.join(stores) 
for fruit, prices in pivot: 
    print fruit.ljust(12), '\t'.join(str(prices[s]) for s in stores) 

輸出:

Fruit  Coles  IGA  Woolw 
Apple  1.5  1.7  1.6 
Banana  0.5  0.7  0.6 
Cherry  5.0  None None 
Date   2.0  None 2.1 
Elderberry None  10.0 None 
+0

'itertools'魔法是我最喜歡的一種魔法。希望別人會發布SQLite解決方案,但這已經比我所做的要好。 – 2012-07-11 09:07:53

+0

@ Li-aungYip SQLite數據透視表中有[不支持](http://www.sqlite.org/cvstrac/tktview?tn=1424),因此在這裏stackoverflow約1000問題問如何做到這一點。但有一個[perl模塊](https://github.com/bduggan/SQLite-VirtualTable-Pivot)就是這樣做的,例如[here](http://search.cpan.org/~bduggan/SQLite- VirtualTable樞軸-0.02/LIB/SQLite的/ VirtualTable/Pivot.pm)。 – sloth 2012-07-11 09:45:55

+0

我最終使用它來編寫一個函數,如上所述創建數據透視表),然後將其作爲臨時表寫回數據庫。這可以讓你在pivoted數據上進一步查詢('JOIN's等)。 臨時表是醜陋的,因爲所有人都出去了,但「如果它是愚蠢的,它的工作原理,它並不愚蠢。」 – 2012-07-13 06:55:18

12

大熊貓包可以非常漂亮的處理這個問題。

>>> import pandas 
>>> df=pandas.DataFrame(data, columns=['Fruit', 'Shop', 'Price']) 
>>> df.pivot(index='Fruit', columns='Shop', values='Price') 
Shop  Coles IGA Woolworths 
Fruit        
Apple   1.5 1.7   1.6 
Banana  0.5 0.7   0.6 
Cherry  5.0 NaN   NaN 
Date   2.0 NaN   2.1 
Elderberry NaN 10.0   NaN 

的文檔: http://pandas.pydata.org/pandas-docs/stable/reshaping.html

一些IPython的筆記本電腦來學習大熊貓: https://bitbucket.org/hrojas/learn-pandas

希望這將有助於。
Registers
Patrick Brockmann