Continuando con mi post anterior, vamos a realizar otra agrupación de datos. Si en el post anterior agrupábamos los datos por el día del mes calculando su suma, ahora vamos a complicarlo un poquito y agrupar por la zona, la planta y el día del mes.
Lo primero los datos, aquí.
La tabla contiene las mismas columnas que en el post anterior:
- ZONA: Zona geográfica donde está situada la planta correspondiente.
- PLANTA: Nombre de la planta.
- DIA_MES: Día del mes del que se han obtenido los datos.
- HORAS_TRABAJO: Las horas de los trabajos que se han ido realizando en la planta.
Con Pandas sería algo trivial:
import pandas as pd
df = pd.read_csv('trabajos_02.csv', sep=";", decimal=",")
grouped_df = df.groupby(['ZONA','PLANTA','DIA_MES']).sum().reset_index()
print (grouped_df)
ZONA PLANTA DIA_MES HORAS_TRABAJO
0 NORTE GORBEA 1 21.783333
1 NORTE GORBEA 2 5.950000
2 NORTE GORBEA 4 14.283333
3 NORTE GORBEA 5 14.366667
4 NORTE GORBEA 6 23.000000
...
23 NORTE GORBEA 25 14.983333
24 NORTE GORBEA 26 15.150000
25 NORTE GORBEA 27 13.833333
26 NORTE GORBEA 28 19.583333
27 NORTE GORBEA 29 14.333333
...
28 SUR TARIFA 1 8.016667
29 SUR TARIFA 4 24.166667
30 SUR TARIFA 5 12.016667
31 SUR TARIFA 6 7.516667
32 SUR TARIFA 7 8.016667
...
42 SUR TARIFA 24 2.250000
43 SUR TARIFA 25 11.950000
44 SUR TARIFA 27 8.033333
45 SUR TARIFA 28 3.433333
46 SUR TARIFA 29 7.850000
Ahora vamos a obtener el mismo resultado, pero sin usar Pandas.
Importamos las librerías que vamos a necesitar:
import csv from itertools import groupby from operator import itemgetter
1.- Leemos el archivo csv. Esta vez vamos a colocarlo en una lista de diccionarios, para poder usar las claves a la hora de agrupar.
csv_rdr = csv.reader(open('trabajos_02.csv'), delimiter=';')
trabajos_lista_dict = []
for index, row in enumerate(csv_rdr):
if index == 0:
encabezado = row
else:
row[3] = float(row[3].replace(",", "."))
d = {}
for index, value in enumerate(row):
key = encabezado[index]
d[key] = value
trabajos_lista_dict.append(d)
Vamos a sacar el primer elemento de la lista, a ver que pinta tiene:
print (trabajos_lista_dict[0])
{'DIA_MES': '01', 'ZONA': 'NORTE', 'PLANTA': 'GORBEA', 'HORAS_TRABAJO': 0.8666666666666667}
Como en el post anterior utilizaremos dos métodos. Primero utilizando la clase groupby y despues usando la clase defaultdict.
1.- Con groupby:
Declaramos una variable tipo lista para ir añadiendo en ella los resultados.
result = []
Creamos el objeto grouper con las claves por las que queremos agrupar
grouper = itemgetter("ZONA", "PLANTA", "DIA_MES")
Utilizamos la clase groupby, con los argumentos nuestra lista de diccionarios ordenada, y la clave para agrupar.
for key, grp in groupby(sorted(trabajos_lista_dict, key = grouper), grouper):
temp_dict = dict(zip(["ZONA", "PLANTA", "DIA_MES"], key))
temp_dict["HORAS_TRABAJO"] = sum(item["HORAS_TRABAJO"] for item in grp)
result.append(temp_dict)
Aquí hay una novedad en el código con respecto al anterior post.
Las keys de la clase groupby van a tener esta pinta:
('NORTE', 'GORBEA', '01')
('NORTE', 'GORBEA', '02')
('NORTE', 'GORBEA', '04')
...
('SUR', 'TARIFA', '01')
('SUR', 'TARIFA', '04')
('SUR', 'TARIFA', '05')
Como vamos a querer como resultado final una lista de diccionarios, vamos a utilizar la función zip para crear los elementos clave-valor para un diccionario temporal para cada grp. Haremos un zip con esta pinta:
zip(["ZONA", "PLANTA", "DIA_MES"], ('NORTE', 'GORBEA', '01')))
Una vez hecho el zip obtenenos un diccionario con esta pinta:
{'PLANTA': 'GORBEA', 'ZONA': 'NORTE', 'DIA_MES': '01'}
El paso siguiente es añadir al diccionario temporal la clave HORAS_TRABAJO, que tendrá como valor la suma de los items del iterador grp, en este caso un diccionario, correspondientes a la clave HORAS_TRABAJO. Luego solo resta añadir el diccionario a la lista result.
Para ver el resultado obtenido podemos hacer:
print ("{:<7}{:<9}{:<11}{:<13}".format("ZONA","PLANTA","DIA_MES","HORAS_TRABAJO"))
for element in result:
zona, planta, dia_mes, horas_trabajo = element['ZONA'],element['PLANTA'],element['DIA_MES'],element['HORAS_TRABAJO']
print ("{:<7}{:<9}{:<11}{:<13}".format(zona, planta, dia_mes, str(horas_trabajo)))
ZONA PLANTA DIA_MES HORAS_TRABAJO
NORTE GORBEA 01 21.783333333333328
NORTE GORBEA 02 5.95
NORTE GORBEA 04 14.283333333333335
NORTE GORBEA 05 14.366666666666664
NORTE GORBEA 06 23.0
...
NORTE GORBEA 25 14.98333333333333
NORTE GORBEA 26 15.15
NORTE GORBEA 27 13.833333333333332
NORTE GORBEA 28 19.583333333333336
NORTE GORBEA 29 14.333333333333336
...
SUR TARIFA 01 8.016666666666666
SUR TARIFA 04 24.166666666666664
SUR TARIFA 05 12.016666666666667
SUR TARIFA 06 7.516666666666667
SUR TARIFA 07 8.016666666666666
...
SUR TARIFA 24 2.25
SUR TARIFA 25 11.950000000000003
SUR TARIFA 27 8.033333333333333
SUR TARIFA 28 3.433333333333333
SUR TARIFA 29 7.85
El resultado coincide con lo obtenido con Pandas.
2.- Con defaultdict.
res_dd = []
d = defaultdict(list)
for row in trabajos_lista_dict:
d[row['ZONA'] + '|' + row['PLANTA'] + '|' + row['DIA_MES']].append(float(row['HORAS_TRABAJO']))
for k, v in sorted(d.items()):
res_dd.append([k, sum(v)])
Con la línea de código 4 nos vamos construyendo las keys, concatenando los valores correspondientes a la zona, la planta y el día del mes.
Vemos el resultado.
print("{:<7}{:<9}{:<11}{:<13}".format("ZONA", "PLANTA", "DIA_MES", "HORAS_TRABAJO"))
for row in res_dd:
zona, planta, dia_mes = row[0].split('|')
print("{:<7}{:<9}{:<11}{:<13}".format(zona, planta, dia_mes, str(row[1])))
ZONA PLANTA DIA_MES HORAS_TRABAJO
NORTE GORBEA 01 21.783333333333328
NORTE GORBEA 02 5.95
NORTE GORBEA 04 14.283333333333335
NORTE GORBEA 05 14.366666666666664
NORTE GORBEA 06 23.0
...
NORTE GORBEA 25 14.98333333333333
NORTE GORBEA 26 15.15
NORTE GORBEA 27 13.833333333333332
NORTE GORBEA 28 19.583333333333336
NORTE GORBEA 29 14.333333333333336
...
SUR TARIFA 01 8.016666666666666
SUR TARIFA 04 24.166666666666664
SUR TARIFA 05 12.016666666666667
SUR TARIFA 06 7.516666666666667
SUR TARIFA 07 8.016666666666666
...
SUR TARIFA 24 2.25
SUR TARIFA 25 11.950000000000003
SUR TARIFA 27 8.033333333333333
SUR TARIFA 28 3.433333333333333
SUR TARIFA 29 7.85
Que también coincide con los anteriores.
Puedes descargarte el código de mi ![]()


