2012-07-11 14 views
5

Me gustaría una forma de resumir una tabla de base de datos para que las filas que comparten una ID común se resumen en una fila de salida.Producir una tabla de resumen ("pivote"?)

Mis herramientas son SQLite y Python 2.x.

Por ejemplo, dada la siguiente tabla de precios de las frutas en mis supermercados locales ...

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

... quiero producir una tabla resumen que me muestra el precio de cada fruta en cada supermercado. Los espacios en blanco deben llenarse con 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 | 
+----------+----------+----------+----------+ 

Creo que la literatura llama a esto una "tabla dinámica" o una "consulta de pivote", pero al parecer SQLite doesn't support PIVOT. (La solución en esa pregunta usos codificados LEFT JOIN s. Esto en realidad no me atrae porque Don 't saber los nombres de "columna" de antemano.)

Ahora hago esto iterando a través de toda la tabla en Python y acumulando un dict de dicts, que es un poco torpe. Estoy abierto a mejores soluciones, ya sea en Python o SQLite, que darán los datos en forma de tabla.

Respuesta

8

Por el lado pitón, usted podría utilizar algunos itertools mágica para la reordenación de sus datos:

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) 

Salida:

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 es mi tipo favorito de magia. Esperando que alguien más publique una solución SQLite, pero esto ya es mejor que lo que estaba haciendo. –

+0

@ Li-aungYip No hay [soporte] (http://www.sqlite.org/cvstrac/tktview?tn=1424) para tablas dinámicas en SQLite, de ahí las ~ 1000 preguntas aquí en stackoverflow preguntando cómo hacer eso. Pero hay un [módulo perl] (https://github.com/bduggan/SQLite-VirtualTable-Pivot) que hace eso, con un ejemplo [aquí] (http://search.cpan.org/~bduggan/SQLite- VirtualTable-Pivot-0.02/lib/SQLite/VirtualTable/Pivot.pm). – sloth

+0

Terminé usando esto para escribir una función que crea la tabla dinámica como la anterior) y luego la vuelvo a escribir en la base de datos como una tabla temporal. Esto le permite realizar consultas adicionales ('JOIN's, etc.) en los datos pivoteados. Las tablas temporales son feas ya que todas salen, pero "si es estúpido y funciona, no es estúpido". –

12

El paquete pandas puede manejar esto muy bien.

>>> 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 documentación: http://pandas.pydata.org/pandas-docs/stable/reshaping.html

algunos cuadernos IPython para aprender pandas: https://bitbucket.org/hrojas/learn-pandas

la esperanza de que le ayudará.
Saludos
Patrick Brockmann