Transformar datos por grupo

Transformación de datos con Polars

Liam Brannigan

Data Scientist & Polars Contributor

¿Por qué comparar con estadísticas por grupo?

Gráfico de series temporales de precios de la electricidad durante un día

  • ¿Los precios están por encima o por debajo de lo normal?
Transformación de datos con Polars

¿Por qué comparar con estadísticas por grupo?

Gráfico de series temporales de precios de la electricidad durante un día con el promedio por hora

Transformación de datos con Polars

¿Por qué comparar con estadísticas por grupo?

Gráfico de series temporales de precios de la electricidad durante un día con el promedio por hora y una anotación que muestra precios bajos al mediodía

Transformación de datos con Polars

¿Por qué comparar con estadísticas por grupo?

Gráfico de series temporales de precios de la electricidad durante un día con el promedio por hora y una anotación que muestra precios normales por la tarde-noche

Transformación de datos con Polars

Extraer la hora

prices.with_columns(
    pl.col("time").dt.hour().alias("hour")
)
| time                | price | solar   | hour |
| ---                 | ---   | ---     | ---  |
| datetime[µs]        | f64   | f64     | i8   |
|---------------------|-------|-------  |------|
| 2025-07-05 10:00:00 | 2.3   | 419.0   | 10   |
| 2025-07-05 11:00:00 | 0.5   | 481.0   | 11   |
| 2025-07-05 12:00:00 | 0.0   | 462.0   | 12   |
Transformación de datos con Polars

Función de ventana con .over()

prices.with_columns(
    pl.col("price").mean()
)
Transformación de datos con Polars

Función de ventana con .over()

prices.with_columns(
    pl.col("price").mean().over("hour")
)
Transformación de datos con Polars

Función de ventana con .over()

prices.with_columns(
    pl.col("price").mean().over("hour").alias("hourly_avg")
)
Transformación de datos con Polars

Función de ventana con .over()

prices.with_columns(
    pl.col("price").mean().over("hour").alias("hourly_avg")
)
| time                | price | solar | hour | hourly_avg |
| ---                 | ---   | ---   | ---  | ---        |
| datetime[µs]        | f64   | f64   | i8   | f64        |
|---------------------|-------|-------|------|------------|
| 2025-07-05 10:00:00 | 2.3   | 419.0 | 10   | 49.6       |
| 2025-07-05 11:00:00 | 0.5   | 481.0 | 11   | 44.4       |
| 2025-07-05 12:00:00 | 0.0   | 462.0 | 12   | 39.5       |
Transformación de datos con Polars

Crear una categoría meteorológica

  • Soleado: solar > 400 W/m²
  • Nublado: solar <= 400 W/m²
Transformación de datos con Polars

Crear una categoría meteorológica

prices.with_columns(
    pl.when(pl.col("solar") > 400)
    .then(pl.lit("sunny"))
    .otherwise(pl.lit("cloudy"))

.alias("weather")
)
| time                | price | solar | weather |
| ---                 | ---   | ---   | ---     |
| datetime[µs]        | f64   | f64   | str     |
|---------------------|-------|-------|---------|
| 2025-07-05 10:00:00 | 2.3   | 419.0 | sunny   |
| 2025-07-06 10:00:00 | 80.5  | 181.0 | cloudy  |
| 2025-07-07 10:00:00 | 41.5  | 150.0 | cloudy  |
Transformación de datos con Polars

Agrupar por varias columnas

prices.with_columns(
    pl.col("price").mean()
)
Transformación de datos con Polars

Agrupar por varias columnas

prices.with_columns(
    pl.col("price").mean().over("hour", "weather")
)
Transformación de datos con Polars

Agrupar por varias columnas

prices.with_columns(
    pl.col("price").mean().over("hour", "weather").alias("avg_by_hour_weather")
)
Transformación de datos con Polars

Agrupar por varias columnas

prices.with_columns(
    pl.col("price").mean().over("hour", "weather").alias("avg_by_hour_weather")
)
| time                | price | hour | weather | avg_by_hour_weather |
| ---                 | ---   | ---  | ---     | ---                 |
| datetime[µs]        | f64   | i8   | str     | f64                 |
|---------------------|-------|------|---------|---------------------|
| 2025-07-05 10:00:00 | 2.3   | 10   | sunny   | 34.2                |
| 2025-07-06 10:00:00 | 80.5  | 10   | cloudy  | 58.0                |
| 2025-07-07 10:00:00 | 41.5  | 10   | cloudy  | 58.0                |
Transformación de datos con Polars

Comparar con la media del grupo

prices.with_columns(
    (pl.col("price")                                     )

)
Transformación de datos con Polars

Comparar con la media del grupo

prices.with_columns(
    (pl.col("price") - pl.col("price").mean().over("hour"))

)
Transformación de datos con Polars

Comparar con la media del grupo

prices.with_columns(
    (pl.col("price") - pl.col("price").mean().over("hour"))
    .alias("diff_from_hourly_avg")
)
| time                | price | hour | diff_from_hourly_avg |
| ---                 | ---   | ---  | ---                  |
| datetime[µs]        | f64   | i8   | f64                  |
|---------------------|-------|------|----------------------|
| 2025-07-05 10:00:00 | 2.3   | 10   | -47.3                |
| 2025-07-06 10:00:00 | 25.1  | 10   | -24.5                |
| 2025-07-07 10:00:00 | 2.7   | 10   | -46.9                |
Transformación de datos con Polars

Otras agregaciones de ventana

.over() funciona con muchas agregaciones:

  • .sum().over() - totales por grupo
  • .max().over() - máximos por grupo
  • .count().over() - tamaños de grupo
Transformación de datos con Polars

¡Vamos a practicar!

Transformación de datos con Polars

Preparing Video For Download...