2012-07-11 11 views
5

Chciałbym podsumować tabelę bazy danych, aby wiersze udostępniające wspólny identyfikator były podsumowane w jednym wierszu danych wyjściowych.Tworzenie tabeli podsumowania ("pivot"?)

Moje narzędzia to SQLite i Python 2.x.

Na przykład podano w poniższej tabeli cen owoców w moich lokalnych supermarketach ...

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

... Chcę stworzyć tabelę podsumowującą pokazując mi cenę każdego owocu w każdym supermarkecie. Puste miejsca powinny być wypełnione przez 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 | 
+----------+----------+----------+----------+ 

wierzę w literaturze nazywa to „tabela pivot” lub „zapytanie pivot”, ale widocznie SQLite doesn't support PIVOT. (Rozwiązanie w tym pytaniu używa jawnie wpisanej LEFT JOIN s. To naprawdę nie odwołania się do mnie, bo don „t znać nazwy«kolumna»z wyprzedzeniem).

teraz robię to przez iteracja całej tabeli w Pythonie i akumulowanie dict z dicts, który jest nieco klutzy. Jestem otwarty na lepsze rozwiązania w Pythonie lub SQLite, które podadzą dane w formie tabelarycznej.

Odpowiedz

8

Na stronie Pythona, można korzystać z niektórych itertools magii rozmieszczanie danych:

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) 

wyjściowa:

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' magic to mój ulubiony rodzaj magii. Mamy nadzieję, że ktoś inny opublikuje rozwiązanie SQLite, ale to już jest lepsze niż to, co robiłem. –

+0

@ Li-aungYip Nie ma [brak wsparcia] (http://www.sqlite.org/cvstrac/tktview?tn=1424) dla tabel przestawnych w SQLite, stąd ~ 1000 pytań tutaj na stackoverflow pytając, jak to zrobić. Ale istnieje moduł [perl] (https://github.com/bduggan/SQLite-VirtualTable-Pivot), który to robi, na przykład [tutaj] (http://search.cpan.org/~bduggan/SQLite- VirtualTable-Pivot-0.02/lib/SQLite/VirtualTable/Pivot.pm). – sloth

+0

Skończyło się na tym, aby napisać funkcję, która tworzy tabelę przestawną, jak powyżej), a następnie zapisuje go z powrotem do bazy danych jako tabeli tymczasowej. Pozwala to na wykonywanie dalszych zapytań ('JOIN's, itp.) Na danych przestawnych. Stoły tymczasowe są brzydkie, ponieważ wszystkie się wydostają, ale "jeśli to głupie i działa, to nie jest głupie". –

12

Pakiet pandy może obsłużyć to bardzo ładnie.

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

Dokumentacja: http://pandas.pydata.org/pandas-docs/stable/reshaping.html

Niektóre ipython Notebooki nauczyć pandy: https://bitbucket.org/hrojas/learn-pandas

nadzieję, że pomoże.
Pozdrawiam
Patrick Brockmann