For AI agents: the complete documentation index is available at https://docs.ovhcloud.com/es/llms.txt, the full documentation bundle is available at https://docs.ovhcloud.com/es/llms-full.txt, and this page is available as Markdown at https://docs.ovhcloud.com/es/guides/public-cloud/data-platform/tutorials-velib-availability-superset-dashboard.md.

Build a Vélib' availability dashboard in Superset

Ver como Markdown

Find out how to build a Superset dashboard on the Vélib' history: bikes available now, daily rhythm, problem stations and daily trends

Objective

This guide walks you through building a Superset dashboard on top of the Vélib' history: where to find a bike right now, how the network breathes during the day, which stations are often empty or full, and how each day compares to the others.

It is the second part of Collect Vélib' availability every hour with SQL only. Superset queries the Lakehouse through Trino, so all SQL on this page is in the Trino dialect.

Requirements

To follow this guide you need:

What you will build

At the end of this part, your dashboard looks like this:

The Now tab of the Vélib' availability dashboard, with the four key figure tiles, the map of the stations by status and the table of empty stations

Map data © OpenStreetMap contributors. Vélib' data © Smovengo / Syndicat Autolib' Vélib' Métropole, published by Ville de Paris under the Open Database License (ODbL).

TabContentDataset
Now4 tiles, map of the stations, table of empty stationsstation_current
Daily rhythmbikes hour by hour, typical day, electric and mechanical bikes, two heatmapsnetwork_hourly
Stationsmost often empty, most often full, docks out of service by communestation_profile
Trendsempty station-hours per day, daily figuresvelib_daily

Every chart follows the same path in Superset: Charts > + Chart, pick the dataset and the chart type, fill in the settings, click Create chart, then Save with the chart name and the dashboard Vélib' availability. The first chart you save creates the dashboard; you lay out the charts in its tabs in Step 5.

Info

Note: your charts will look like the screenshots, but not with the same values: the figures depend on when you collect and for how long. The Now tab is complete from the first collection. The Daily rhythm, Stations and Trends tabs only take a similar shape a few days later: until then, the lines are short, the heatmaps have empty cells and the rankings still move.

Instructions

Step 1: Building the Now tab

These charts use the dataset station_current: one row per station, at the latest collection.

Key figures

The four tiles use the chart type Big Number.

TileMetricSubheaderNumber format
Bikes available nowSimple tab: column bikes, aggregate SUMbikes in stations, latest collection,d
Electric bikesCustom SQL: SUM(ebike) * 1e0 / NULLIF(SUM(bikes), 0)of available bikes are electric.1%
Empty stationsCustom SQL: SUM(CASE WHEN bikes = 0 AND is_open THEN 1 ELSE 0 END)open stations with no bike,d
Docks out of serviceCustom SQL: SUM(CASE WHEN is_open THEN out_of_service_docks ELSE 0 END)docks neither free nor holding a bike,d

Expected values, at the time of writing: about 19,000 bikes, about 40% electric bikes, about 100 empty stations and more than 1,000 docks out of service. The figures change with each collection.

1e0 avoids an integer division, which would return 0. A closed station is not counted as empty, and in a closed station every dock looks unavailable: the last two tiles only count open stations.

The Bikes available now Big Number chart with the metric SUM(bikes), showing 18,931

Stations by status

The map shows every station, coloured by its state at the latest collection.

SettingValue
Chart typedeck.gl Scatterplot
Longitude & Latitudelon and lat
Row limit10000
Ignore null locationschecked
Categorical Colorstatus
Minimum Radius3
Tooltip contentsempty
Customize tooltips templateempty

Use deck.gl Scatterplot: it is the only map type that draws one point per station with a colour per category. MapBox needs a Mapbox key, which means a third-party account. The grid and hexagon maps group the stations into cells, and lose the station.

The Stations by status deck.gl Scatterplot with the Categorical Color set to status, and the map of Paris with one point per station coloured as Closed, Available, Empty or Full

Map data © OpenStreetMap contributors.

Empty stations right now

The table gives the details that the map cannot show in a tooltip.

SettingValue
Chart typeTable
Query modeRaw records
Columnsstation_name, commune, capacity, free_docks, out_of_service_docks
Filtersstatus equal to Empty
Orderingcapacity, descending
Row limit250

Raw records shows one row per station, without grouping. Sorting by capacity brings the largest empty stations first: they leave the most users without a bike.

The table holds as many rows as the Empty stations tile shows. For each station, free_docks plus out_of_service_docks equals capacity: an empty station has no bike, so every dock is either free or out of service.

The Empty stations right now table in Raw records mode, filtered on status Empty and ordered by capacity

Step 2: Building the Daily rhythm tab

These charts use the dataset network_hourly: one row per hour for the whole network. They fill in as the collection goes on.

Bikes in stations, hour by hour

The network breathes: available bikes drop when they are on the road, and come back at night.

SettingValue
Chart typeLine Chart
X-axiscollected_hour_paris
Time grainHour
MetricsSimple tab: column bikes, aggregate MAX
Filterscollected_hour_paris: Last week

network_hourly already holds one row per hour, so the aggregate groups nothing: MAX returns the value of the hour. The only exception is the night the clocks go back, when two UTC hours share the same Paris hour: MAX then keeps the higher of the two instead of adding them up. The filter keeps the last seven days, 168 points, so the chart stays readable as the collection grows.

The Bikes in stations, hour by hour line chart over the last week, with a peak above 20,000 bikes each night and a drop each day

This chart shows what really happened, day after day. The next one averages all days into a typical day.

Typical day

The average day, hour by hour, with one line for weekdays and one for weekends.

SettingValue
Chart typeLine Chart
X-axishour_of_day
MetricsSimple tab: column bikes, aggregate AVG
Dimensionsday_type
X-axis sortaxis value, ascending

The X-axis is the hour of the day, from 0 to 23: every 8 a.m. is grouped together, whatever the day, and the average gives the typical number of bikes available at 8 a.m. The Weekend line appears on its own once the collection covers a Saturday.

On weekdays, the line drops at the morning rush hour, around 9 a.m., and even lower at the evening one, around 6 p.m.

The Typical day line chart from 0 to 23 hours, with one line for weekdays and one for weekends, both at their lowest around 6 p.m.

Electric and mechanical bikes

Two lines, one per type of bike, to compare how each one varies.

SettingValue
Chart typeLine Chart
X-axiscollected_hour_paris
Time grainHour
MetricsSimple tab: MAX of mechanical, then MAX of ebike
Filterscollected_hour_paris: Last week

The electric bikes line swings much more than the mechanical one, between night and rush hours.

The Electric and mechanical bikes line chart over the last week, with the electric bikes line swinging much more than the mechanical one

When is it hard to find a bike?

A heatmap of the day of the week against the hour, coloured by the share of empty stations. The darkest cells are the time slots when finding a bike is the hardest.

SettingValue
Chart typeHeatmap
X-axishour_of_day
Y-axisday_of_week
MetricCustom SQL: AVG(empty_stations * 1e0 / stations)
Sort X AxisAxis ascending
Sort Y AxisAxis descending
Normalize Acrossheatmap
Value Format.1%

The metric divides empty stations by open stations, so the share stays comparable when a few stations close or reopen. 1e0 avoids an integer division.

Sort both axes by their value: the default order follows the query results, and Metric ascending would sort the hours by their share of empty stations. Axis ascending puts the hours from 0 to 23, and Axis descending on the Y-axis puts Monday at the top, like a calendar.

On weekdays, the darkest cells come late in the morning, between 9 and 11 a.m., with up to about 10% of empty stations. Nights and weekends are the lightest.

This does not contradict the typical day, where the fewest bikes are parked around 6 p.m. The evening has fewer bikes in stations, but in the morning they are spread less evenly: the next heatmap shows that full stations also peak late in the morning. Some stations run empty while others fill up, and the number of empty stations measures that imbalance, not the number of bikes.

The When is it hard to find a bike? heatmap of days of the week against hours, darkest on weekdays between 9 and 11 a.m.

When is it hard to return a bike?

The mirror heatmap: the share of open stations with no free dock, where users cannot return their bike.

The quickest way is to start from the previous chart: change the metric, click Save, select Save as... and enter the new name.

SettingValue
Chart typeHeatmap
X-axishour_of_day
Y-axisday_of_week
MetricCustom SQL: AVG(full_stations * 1e0 / stations)
Sort X AxisAxis ascending
Sort Y AxisAxis descending
Normalize Acrossheatmap
Value Format.1%

Keep the same sorts as the first heatmap, so that both read cell by cell. Each heatmap has its own colour scale, from its own minimum to its own maximum: compare the values, not only the colours.

Full stations do not peak at the same hours as empty ones: the darkest cells come at night on weekdays, and again late in the morning, with up to about 5.5% of full stations.

The heatmap of full stations, darkest on weekday nights and late on weekday mornings

Step 3: Building the Stations tab

These charts use the dataset station_profile: one row per station, over the whole collection. All three use the chart type Bar Chart, with the Horizontal orientation: it leaves room for the names.

Most often empty

The ten stations that spend the most time without any bike.

SettingValue
X-axisstation_name
MetricsSimple tab: column empty_hours_pct, aggregate MAX
Row limit10
X-axis sortby the metric, descending
OrientationHorizontal, in the Customize tab
Axis titleShare of hours with no bike (%)

station_profile already holds one row per station, so MAX returns the share of the station.

The chart ranks the ten stations by their share of hours with no bike.

The Most often empty horizontal bar chart, ranking ten stations by their share of hours with no bike

Most often full

The ten stations where users cannot return their bike, for lack of a free dock.

SettingValue
X-axisstation_name
MetricsSimple tab: column full_hours_pct, aggregate MAX
Row limit10
X-axis sortby the metric, descending
OrientationHorizontal, in the Customize tab
Axis titleShare of hours with no free dock (%)

The quickest way is to start from the previous chart: change the metric and the axis title, click Save, select Save as... and enter the new name. The chart ranks the ten stations by their share of hours with no free dock.

The horizontal bar chart ranking ten stations by their share of hours with no free dock

Docks out of service by commune

A maintenance view: where broken docks are, relative to the number of docks of each commune.

SettingValue
X-axiscommune
MetricsCustom SQL: SUM(avg_out_of_service_docks) * 1e0 / SUM(capacity)
FiltersCustom SQL, clause HAVING: COUNT(*) >= 5
Row limit15
X-axis sortby the metric, descending
OrientationHorizontal, in the Customize tab
Number format.1%

A share rather than a number of docks: the communes have very different numbers of stations, and the largest would dwarf the others in absolute numbers. The HAVING filter applies after the grouping by commune, and leaves out communes with fewer than 5 stations, where a single broken dock would push them to the top.

The chart ranks the communes by their share of docks out of service.

The Docks out of service by commune horizontal bar chart with the HAVING filter COUNT(*) >= 5, ranking fifteen communes by their share of docks out of service

These charts use the dataset velib_daily: one row per day for the whole network. They need several days of collection.

Empty station-hours per day

One bar per day: the total of hours spent empty by all stations, an indicator of how hard it was to find a bike that day.

SettingValue
Chart typeBar Chart
X-axisday
Time grainDay
MetricsSimple tab: column empty_station_hours, aggregate MAX
Dimensionsday_type
FiltersCustom SQL, clause WHERE: observed_hours >= 23

Only complete days count: a day with a few hours of collection would have fewer empty hours, and could not be compared. The threshold of 23 hours rather than 24 tolerates one missed hour. The dimension day_type colours weekdays and weekends differently: weekends stay well below weekdays.

Many factors move these figures from one day to the next: the weather (rain and cold keep users off bikes), school holidays, public holidays, strikes or disruptions on public transport (which send more users to Vélib') and large events. A public holiday, such as 11 November, shows as a weekday, but should look like a Sunday. Compare similar days, and read a change over several days rather than on a single bar.

The Empty station-hours per day bar chart, with weekdays between about 1,300 and 2,000 empty station-hours and weekends lower

Daily figures

The full table of daily figures, to read the exact values behind the charts.

SettingValue
Chart typeTable
Query modeRaw records
Columnsday, day_type, observed_hours, min_bikes, max_bikes, daily_swing, avg_fill_rate_pct, empty_station_hours, peak_empty_stations
Orderingday, descending
Row limit100
Show cell barsunchecked, in the Customize tab
Timestamp format%Y-%m-%d, in the Customize tab

Unlike the previous chart, the table keeps incomplete days: the column observed_hours shows which days are complete, and reveals a day with missing collections. The first day of collection, which starts at noon in the screenshot, and the current day show fewer than 24 observed hours.

On a weekday, the network goes from about 20,000 parked bikes at night to about 16,000 to 17,000 at the busiest hour: some 3,000 to 5,000 bikes are in use at the peak.

The Daily figures table in Raw records mode, one row per day with the observed hours, the fewest and most bikes and the daily swing

Step 5: Assembling the dashboard

  1. Open Dashboards, then the dashboard Vélib' availability, and click Edit dashboard.

  2. From Layout elements, add a Tabs component with 4 tabs: Now, Daily rhythm, Stations and Trends.

  3. From Charts, place the charts in each tab:

    TabCharts, in orderLayout
    NowBikes available now, Electric bikes, Empty stations, Docks out of service, Stations by status, Empty stations right nowthe four tiles on one row, then the map and the table at full width
    Daily rhythmBikes in stations, hour by hour, Typical day, Electric and mechanical bikes, When is it hard to find a bike?, When is it hard to return a bike?the timeline at full width, the typical day and the electric bikes side by side, then the two heatmaps at full width
    StationsMost often empty, Most often full, Docks out of service by communethe two rankings side by side, then the communes at full width
    TrendsEmpty station-hours per day, Daily figuresthe chart at full width, then the table
  4. Click Save.

The Daily rhythm tab of the dashboard, with the hour by hour timeline, the typical day and the electric bikes side by side, and the two heatmaps

What you have built

You have a four-tab dashboard that turns a raw Vélib' history into answers: where to find a bike now, when the network is under strain, which stations fail their users most often, and how each day compares to the others.

From here you can add dashboard filters on commune, or apply the same pipeline to another public API that only gives a current state. For another Superset dashboard built on Data Platform, see Build a sales dashboard for an online store in Superset.

Go further

For training or technical assistance implementing our solutions, contact your sales representative or visit our Professional Services page to request a quote and have your project analysed by our experts.

Ask questions, give your feedback and interact directly with the team building the Data Platform on the dedicated Discord channel.

If you need support with your OVHcloud services, create a request in our Help Centre.

Join our community of users.

¿Le ha resultado útil esta página?