Citi Bike Trips Per Borough

This page recreates the final plot shown just before the Load section in chapter 1 of Python Polars: The Definitive Guide, using plotnine_polars.

To keep the example focused on plotting, it uses a compact pre-aggregated table with daily trip counts by borough for March 2024.

import polars as pl
import plotnine_polars
from mizani.labels import label_comma
from plotnine import element_line, element_rect, element_text

Read the data

trips_per_day = (
    pl.read_csv(
        "../data/citi-bike-trips-per-day.csv",
        try_parse_dates=True,
    )
    .with_columns(
        pl.col("borough_start").cast(
            pl.Enum(["Bronx", "Brooklyn", "Manhattan", "Queens"])
        )
    )
)

trips_per_day
shape: (124, 3)
borough_start datetime_start num_trips
enum datetime[μs] i64
"Bronx" 2024-03-01 00:00:00 2748
"Brooklyn" 2024-03-01 00:00:00 20068
"Manhattan" 2024-03-01 00:00:00 56434
"Queens" 2024-03-01 00:00:00 5728
"Bronx" 2024-03-02 00:00:00 1010
"Queens" 2024-03-30 00:00:00 6583
"Bronx" 2024-03-31 00:00:00 2724
"Brooklyn" 2024-03-31 00:00:00 25940
"Manhattan" 2024-03-31 00:00:00 54440
"Queens" 2024-03-31 00:00:00 6237

Plot

(
    trips_per_day.ggplot()
    .aes(x="datetime_start", y="num_trips", fill="borough_start")
    .geom_area()
    .scale_fill_brewer(type="qual", palette=2)
    .scale_x_datetime(date_labels="%-d", date_breaks="1 day", expand=(0, 0))
    .scale_y_continuous(labels=label_comma(), expand=(0, 0))
    .labs(
        x="March 2024",
        fill="Borough",
        y="Trips per day",
        title="Citi Bike trips per day in March 2024",
        subtitle="On March 23, nearly 10 cm of rain fell in NYC",
    )
    .theme_tufte(base_size=14)
    .add_theme(
        axis_ticks_major=element_line(color="white"),
        figure_size=(8, 5),
        legend_position="top",
        plot_background=element_rect(fill="white", color="white"),
        plot_caption=element_text(style="italic"),
        plot_title=element_text(ha="left"),
    )
)