2012-07-11 13 views
5

Vorrei un modo per riepilogare una tabella di database in modo che le righe che condividono un ID comune vengano riepilogate in una riga di output.Produrre una tabella di riepilogo ("pivot"?)

I miei strumenti sono SQLite e Python 2.x.

Ad esempio, data la seguente tabella dei prezzi della frutta ai miei supermercati locali ...

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

... voglio produrre una tabella riassuntiva che mostra me il prezzo di ogni frutto in ogni supermercato. Gli spazi vuoti dovrebbero essere occupati da 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 | 
+----------+----------+----------+----------+ 

Credo che la letteratura definisce questa una "tabella pivot" o di una "interrogazione pivot", ma a quanto pare SQLite doesn't support PIVOT. (La soluzione in questa domanda utilizza in hardcoded LEFT JOIN s. Questo in realtà non appello perché ho don conoscere i nomi di "colonna" in anticipo.)

In questo momento lo faccio iterando attraverso l'intera tabella in Python e accumulando uno dict di dicts, che è un po 'klutzy. Sono aperto a soluzioni migliori, sia in Python che in SQLite, che forniranno i dati in forma tabellare.

risposta

8

Sul lato di pitone, si potrebbe usare un po 'di magia itertools per riorganizzare i dati:

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) 

uscita:

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

La magia di 'itertools' è il mio genere di magia preferito. Sperando che qualcun altro pubblichi una soluzione SQLite, ma questo è già migliore di quello che stavo facendo. –

+0

@ Li-aungYip C'è [nessun supporto] (http://www.sqlite.org/cvstrac/tktview?tn=1424) per le tabelle pivot in SQLite, quindi le ~ 1000 domande qui su StackOverflow che chiedono come farlo. Ma c'è un [perl module] (https://github.com/bduggan/SQLite-VirtualTable-Pivot) che lo fa, con un esempio [qui] (http://search.cpan.org/~bduggan/SQLite- VirtualTable a perno-0,02/lib/SQLite/VirtualTable/Pivot.pm). – sloth

+0

Ho finito usando questo per scrivere una funzione che crea la tabella pivot come sopra) e poi la scrive sul database come una tabella temporanea. Ciò consente di eseguire ulteriori query ('JOIN's, ecc.) Sui dati pivot. I tavoli temporanei sono brutti come tutti escono, ma "se è stupido e funziona, non è stupido". –

12

Il pacchetto panda in grado di gestire questo molto bene.

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

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

Alcuni ipython Notebook da imparare panda: https://bitbucket.org/hrojas/learn-pandas

speranza che aiuterà.
Saluti
Patrick Brockmann

Problemi correlati