2012-07-11 35 views
5

Bir veritabanı tablosunu özetlemek için bir yol belirtmek istiyorum, böylece ortak bir kimliği paylaşan satırlar bir satır çıktı olarak özetlenir.Bir özet ("pivot"?) Tablosu üretin

Araçlarım, SQLite ve Python 2.x. Benim yerel süpermarketler meyve fiyatlarının Aşağıdaki tabloda verilen Örneğin

...

+--------------------+--------------------+--------------------+ 
|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    | 
+--------------------+--------------------+--------------------+ 

... Ben her süpermarkette bana her meyvenin fiyatı gösteren bir özet tablo üretmek istiyoruz. Boş alanlar NULL'lar tarafından doldurulmalıdır.

+----------+----------+----------+----------+ 
|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 | 
+----------+----------+----------+----------+ 

Ben literatür bu bir "özet tablo" ya da bir "eksen sorgu" olarak adlandırdığı inanıyorum, ama görünüşe SQLite doesn't support PIVOT. (yani söz konusu çözüm kodlanmış LEFT JOIN s kullanır. Bu gerçekten bana hitap etmiyor çünkü don "sütun" adlarını önceden bilin.)

Şu anda bunu Python'daki tüm tablo boyunca yineleyerek ve dict bir bit klutzy olan biriktirerek yapıyorum. Python veya SQLite'de, verileri tablo biçiminde verecek daha iyi çözümlere açığım.

cevap

8

piton tarafında, verilerinizi yeniden düzenleyerek bazı itertools büyü kullanabilirsiniz:

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) 

Çıktı:

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

İtertools'un sihiri, benim en sevdiğim sihirdir. Bir başkasını umuduyla bir SQLite çözümü yayınlayacak, ancak bu zaten yaptığımdan daha iyi. –

+0

@ Li-aungYip SQLite'deki pivot tabloları için [destek] yok (destek yok) (http://www.sqlite.org/cvstrac/tktview?tn=1424), dolayısıyla stackoverflow'ta bunun nasıl yapılacağını soran ~ 1000 soru var. Ama bir [perl modülü] (https://github.com/bduggan/SQLite-VirtualTable-Pivot) var, bu bir örnek ile [burada] (http://search.cpan.org/~bduggan/SQLite- VirtualTable-Pivot 0.02/lib/SQLite/VirtualTable/Pivot.pm). – sloth

+0

Yukarıdaki gibi pivot tablosunu oluşturan bir işlev yazmak için bunu kullanarak bitti ve sonra veritabanına geçici bir tablo olarak geri yazar. Bu, döndürülen verilerde daha fazla sorgu ("JOIN's, vb.) Yapmanıza izin verir. Geçici tablolar çirkindir, ama "aptalca ve işe yarıyorsa, aptal değil." –

12

pandalar paketi çok güzel bu işleyebilir.

>>> 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 

belgeler: Bazı ipython Defterler panda öğrenmek http://pandas.pydata.org/pandas-docs/stable/reshaping.html

: https://bitbucket.org/hrojas/learn-pandas

Umut yardımcı olacaktır.
Saygılar
Patrick Brockmann