We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Time-Based Operations

Time-based operations require a datetime-type column in both Pandas and Polars. In Pandas, we often make that column the index, i.e., a DatetimeIndex:

sales = pd.DataFrame(
    {
        "date": ["2024-05-01 14:30", "2024-05-02 09:00", "2024-05-02 16:45"],
        "sku": ["TSH-BLU-MED", "AP-AN001-SM", "TSH-BLU-MED"],
        "quantity": [2, 1, 4],
        "unit_price": [19.99, 29.99, 19.99],
    }
)

# Add a column calculating total revenue for each sale
sales["line_total"] = sales["quantity"] * sales["unit_price"]

# Convert the date column to datetime, and set it as the index for resampling
sales["date"] = pd.to_datetime(sales["date"])
sales = sales.set_index("date")

# Resample to group rows by day, and sum line_total for daily revenue
daily_revenue = sales.resample("D")["line_total"].sum()
print(daily_revenue)
# date
# 2024-05-01     39.98
# 2024-05-02    109.95

In Polars, you can use time-based operations directly on a datetime-type column. No need to muck with indexes:

incidents = pl.DataFrame(
    {
        "opened_at": ["2024-05-01 14:30", "2024-05-02 09:00", "2024-05-02 16:45"],
        "ticket_id": ["T-1", "T-2", "T-3"],
        "response_minutes": [45, 30, 90],
    }
)

# Convert the opened_at column to datetime
incidents = incidents.with_columns(
    pl.col("opened_at").str.strptime(pl.Datetime, "%Y-%m-%d %H:%M")
)

# Group by date (truncated to day), and average response_minutes
daily_response = incidents.group_by(pl.col("opened_at").dt.truncate("1d")).agg(
    pl.col("response_minutes").mean().alias("avg_response_minutes")
)
print(daily_response)
# shape: (2, 2)
# ┌─────────────────────┬──────────────────────┐
# │ opened_at           ┆ avg_response_minutes │
# │ ---                 ┆ ---                  │
# │ datetime[μs]        ┆ f64                  │
# ╞═════════════════════╪══════════════════════╡
# │ 2024-05-01 00:00:00 ┆ 45.0                 │
# │ 2024-05-02 00:00:00 ┆ 60.0                 │
# └─────────────────────┴──────────────────────┘

The result has one row per day and an average response time for that day. The important Polars-specific pieces are:

  • .group_by() groups rows by a column or expression
  • .dt accesses datetime-specific methods on a datetime column
  • .dt.truncate() truncates a datetime to a time unit, like "1d" for "day"
  • .agg() aggregates grouped rows with expressions like sum() or mean()

Assignment

SnackStack's appliances send energy readings throughout the day. The analytics team needs a daily total so they can spot usage spikes.

Complete the build_daily_energy_report function. It accepts a Polars DataFrame of device energy readings and returns a new report DataFrame.