Saltar al contenido

Indice / Practicas / EJ-3.5

EJ-3.5 · Resumir una grilla de sensores por eje

Practica de: 3.2 VectorizacionDificultad: B

Una grilla de 10 sensores × 24 horas, resumida a una fila por sensor. La práctica del axis=, con dos decisiones que hay que tomar antes de reducir.

Qué hay que hacer

A partir de numpy_sensores.csv (10 filas, 240 lecturas), producir sensores_resumen.csv con una fila por sensor y ocho columnas: identificación, cuántas lecturas quedaron usables, mínima, máxima, media, amplitud y la hora del pico.

Archivos

ELI5Explicado facil

Es el parte diario de cada sensor: cuántas veces midió, qué tan frío y qué tan calor, y a qué hora fue el pico.

Lo único que no es obvio: qué contar como «midió». Una celda vacía no midió. Y un sensor que dice 999,9 grados tampoco - aunque haya escrito un número.

Las dos decisiones, antes de reducir

Si reducís primero, los números salen mal y no lo vas a notar
  • Con np.mean en vez de np.nanmean, tres sensores dan nan: S03, S06 y S09, que son los que tienen huecos.
  • Sin marcar el 999.9 de S05, su media da 60,65 en vez de 19,81, y su máxima da 999,9. El número sale, se ve raro, y nada falla.

El rango válido - −10 a 50 grados - lo fija el enunciado, no los datos. Ninguna función de NumPy puede saberlo.

La comprobación que cierra el ejercicio

lecturas_validas.sum() tiene que dar 235: 240 celdas, menos 4 vacías, menos 1 imposible.

Si te daQué falta
235Está bien
236No marcaste el 999.9
239Marcaste el imposible pero no contaste los ausentes
240No hiciste ninguna de las dos cosas

Cómo saber si te salió

python comparar.py mi_resumen.csv sensores_resumen.csv

Antes de arrancar, mirá los datos

numpy_sensores.csv (entrada) · 10 filas, se muestran 5
sensor_idubicacionh00h01h02h03h04h05h06h07h08h09h10h11h12h13h14h15h16h17h18h19h20h21h22h23
S01deposito20.819.819.219.019.620.320.021.021.121.721.922.922.623.723.924.324.423.323.222.322.421.921.221.1
S02sala_servidores18.517.116.616.116.617.018.318.418.919.919.721.221.721.922.123.322.622.021.620.220.319.519.218.2
S03oficina17.816.616.615.516.116.517.4vaciovacio18.519.619.620.320.321.420.720.920.420.419.119.519.018.317.9
S04planta_baja21.220.820.019.919.620.120.821.021.021.921.622.822.822.923.123.923.023.222.521.921.821.521.020.9
S05laboratorio19.918.718.918.218.518.918.819.519.819.820.2999.920.820.520.420.821.221.020.020.720.220.319.419.2

El contrato de salida

sensores_resumen.csv · 10 filas

ColumnaTipoQue lleva
sensor_idtextoEl identificador tal cual vino: S01 a S10
ubicaciontextoLa ubicacion tal cual vino
lecturas_validasenteroCuantas de las 24 lecturas quedan despues de descartar ausentes e imposibles
minimadecimalLa lectura mas baja valida, 1 decimal
maximadecimalLa lectura mas alta valida, 1 decimal
mediadecimalEl promedio de las validas, 2 decimales
amplituddecimalmaxima menos minima, 1 decimal
hora_picotextoEl nombre de la columna donde ocurre la maxima: h00 a h23

Orden de las filas: sensor_id ascendente. Los 10 son distintos, asi que el orden es total y no hace falta desempate. Indice: no se escribe: to_csv(index=False)

Que hacer con cada defecto

DefectoDondeAccionAdonde va
celdas vacias4 celdas: S03 en h07 y h08, S06 en h13, S09 en h21no no participan de ninguna reduccion. Bajan lecturas_validas, y por lo tanto el denominador de la mediasensores_resumen.csv: se ven en la columna lecturas_validas
lectura fuera del rango fisico1 celda: S05 en h11 marca 999.9marcarla marcarla como ausente ANTES de reducir. El rango valido es -10 a 50 grados y lo fija el enunciado, no los datossensores_resumen.csv: S05 queda con 23 lecturas validas
empate en el maximo de una fila0 filas en este archivogana gana la hora mas temprana, que es lo que devuelve nanargmaxsensores_resumen.csv, columna hora_pico
Orden de comprobacion

Una fila puede tener mas de un problema. Se informa solo el primero de esta lista:

  1. leer las 24 columnas horarias como una grilla numerica (10, 24)
  2. marcar como ausente lo que este fuera de -10 a 50
  3. contar las validas por fila
  4. recien entonces reducir: minimo, maximo, media y posicion del maximo, todos con axis=1

Si se reduce antes de marcar el imposible, la media de S05 da 60,65 en vez de 19,81 y su maxima da 999,9. Y si se usa mean en vez de nanmean, las tres filas con hueco dan nan. Las dos decisiones se toman ANTES de la reduccion, no despues.

Conteos clave

Si estos numeros no te dan, algo se desvio antes de que llegues a comparar los archivos.

filas de entrada10
celdas de lectura240
sensores_resumen.csv10
celdas descartadas5
sensores con las 24 lecturas6
por motivoausente: 4, fuera_de_rango: 1

Invariantes

Comprobaciones que tu resultado tiene que cumplir. Corrilas vos mismo antes de comparar los archivos:

len(resumen) == 10
resumen['sensor_id'].is_unique
resumen['sensor_id'].is_monotonic_increasing
not resumen.isna().any().any()
resumen['lecturas_validas'].sum() == 235
resumen['lecturas_validas'].between(1, 24).all()
(resumen['minima'] <= resumen['media']).all()
(resumen['media'] <= resumen['maxima']).all()
(resumen['maxima'] <= 50).all()
(resumen['amplitud'] - (resumen['maxima'] - resumen['minima'])).abs().max() < 0.05
resumen['hora_pico'].str.match(r'h\d{2}$').all()
PISTASSi te trabas, abri esto
  • axis=1 elimina las 24 horas y deja un valor por sensor. Si tu resultado tiene 24 filas, invertiste el eje.
  • np.where(valida, grilla, np.nan) marca sin descartar: la grilla sigue siendo (10, 24) y las reducciones por eje siguen funcionando.
  • np.nanargmax(a, axis=1) devuelve la POSICION del maximo dentro de cada fila. El nombre de la hora sale de indexar la lista de columnas con esa posicion.
  • La suma de lecturas_validas tiene que dar 235: 240 celdas menos 4 vacias menos 1 imposible. Si te da 236, no marcaste el 999.9; si te da 240, tampoco marcaste los ausentes.

Así tiene que quedar

sensores_resumen.csv (objetivo) · 10 filas, se muestran 5
sensor_idubicacionlecturas_validasminimamaximamediaamplitudhora_pico
S01deposito2419.024.421.735.4h16
S02sala_servidores2416.123.319.627.2h15
S03oficina2215.521.418.755.9h14
S04planta_baja2419.623.921.634.3h15
S05laboratorio2318.221.219.813.0h16
axis=1, no axis=0

El eje que se nombra es el que desaparece. Acá hay que eliminar las 24 horas para dejar un valor por sensor, así que va axis=1. Si tu resultado tiene 24 filas en vez de 10, invertiste el eje.

La hora del pico

np.nanargmax(a, axis=1) devuelve la posición del máximo dentro de cada fila, no el valor. El nombre de la hora sale de indexar la lista de columnas con esa posición.

Si hubiera empate, gana la hora más temprana - que es lo que nanargmax devuelve por su cuenta. En este archivo no hay ninguno, pero el contrato lo declara igual.