Concepts / Working with Time-Indexed Data in pandas

Working with Time-Indexed Data in pandas

The case study predicts how many people rent a bike at one Citi Bike station for a given time, using station data loaded for August 2015.

  • Programming

A Practical Question About Bikes at One Station

Andreas wants to know whether any bikes will be left at the rental station in front of his house. That is a practical question, and this case study answers it by working with real rental data rather than a formula. In New York, Citi Bike runs a network of bicycle rental stations spread across the city, operating on a subscription system. Because the bike rental data is made public in an anonymized form, it can be analyzed in many different ways.

The prediction task is precise: for a given time and day, estimate how many people will rent a bike at that station. Everyday knowledge helps here. Anyone who has watched a busy street knows that rentals rise and fall with the time of day. The rest of this article follows the code that prepares the data for that prediction, and it asks you to check the output of each step as you go, so that you can tell where a result would go wrong if it did.

Loading One Station's Rentals

The first step loads the August 2015 data for one particular station as a pandas DataFrame. A helper function from the mglearn library returns that data, and the result is assigned to a variable named citibike. At this point nothing about the prediction happens yet. The line only brings the data into memory, so it is worth reading it as a loading step and nothing more.

Once the data is loaded, the cheapest way to check it is to look at the first rows. The head() method shows those rows together with their time labels, so you can confirm that the data is the station you intended before going further. The diagram below shows the shape of the printed table for the first five intervals.

00:003.003:000.006:009.009:0041.012:0039.0
Each three-hour time label in the index is paired with one floating-point value. The printed first five rows carry 3.0, 0.0, 9.0, 41.0 and 39.0.

The printed table has two parts that matter. The index is labeled starttime, and each row carries one value. Each row covers one three-hour interval, and the value is the figure the data holds for that interval. The values are shown with a decimal point, such as 3.0 and 41.0. That tells you the column is stored as floating-point numbers, even though the quantities being counted are rentals.

Reading the Pairing of Labels and Values

Each time label is the start of its interval, and each value belongs to the label it is paired with. The pairing is the single most important thing to read correctly in the printed table. If you attach a value to the wrong label, you will reason about the wrong part of the day. For example, attaching 41.0 to the 06:00 label would make you think the station was busy at 06:00, when that value belongs to a different interval.

What do you think happens?

Which value belongs to the 06:00 label in the printed first five rows?

  • 3.0

  • 0.0

  • 9.0

  • 41.0

Reveal answer
Answer:

9.0

The rows run in order from midnight in three-hour steps, so the 00:00 row is first, the 03:00 row is second, and the 06:00 row is third. The third row carries 9.0. The value 41.0 is the fourth row, which belongs to the 09:00 interval, not to 06:00.

What Resampling Does to the Rows

The source states that the data is resampled into three-hour intervals to obtain the main trends. Resampling means regrouping observations that are tied to time into new, regular time buckets, and then working with one value per bucket. Here the bucket width is three hours, which is the meaning of the Freq: 3H label in the printed output. A bucket that begins at midnight, then 03:00, then 06:00, and so on, gives one row per interval across each day.

The effect on the rows is a change in granularity. Many individual rental observations that fall inside one three-hour window are replaced by a single row for that window. The row's value is the count the data holds for that interval. The diagram below shows two adjacent buckets, with several raw rental observations feeding each bucket and one value coming out.

Rentals from 00:00to 03:00many observations00:00 row3.0Rentals from 03:00to 06:00many observations03:00 row0.0reduced to one valuereduced to one value
Many rental observations inside one three-hour window collapse into one row labeled with that window's start time. The first two output rows print 3.0 and 0.0.

Why Three Hours Reveals the Trend

The reason for this choice is the trend, not the detail. A single bucket that covers three hours smooths out minute-to-minute noise and leaves the daily pattern visible. The source describes the goal as obtaining the main trends for each day. In other words, the resampled table answers how activity moves across a day, which is the kind of question Andreas needs answered.

Worked example

Reading the First Three Buckets as a Daily Pattern

Using the first three resampled rows of the station data, which print 3.0, 0.0 and 9.0 under the 00:00, 03:00 and 06:00 labels, describe what the rows show about activity from midnight to 06:00.

  1. 1
    Identify the row order

    The buckets begin at midnight and advance in three-hour steps, so the rows are read in order: 00:00, then 03:00, then 06:00.

  2. 2
    Pair each label with its value

    The 00:00 label carries 3.0, the 03:00 label carries 0.0, and the 06:00 label carries 9.0. Each value stays attached to the label that starts its interval.

  3. 3
    Read the change across buckets

    The count drops from 3.0 to 0.0 between midnight and 03:00, then rises to 9.0 by 06:00. Each step compares one three-hour window with the next.

Result

The rows show a quiet window between 03:00 and 06:00 at the start of the day, followed by a rise by 06:00. This is a trend across the day rather than a single minute of activity.

Tracing the Data Through Each Stage

After loading and resampling, the next move is visual. The source shows a plot of the rental frequencies for the whole month, with the number of bike rentals drawn over time for the selected station. Each point on the plot corresponds to one of the resampled three-hour rows, so the plot is a picture of the same table you printed earlier, extended across August 2015. Peaks and quiet stretches become visible as a pattern across days, which a list of printed numbers hides.

The order of these stages is part of the lesson. Each stage consumes the output of the stage before it. The loaded DataFrame feeds the resampling step, and the resampled table feeds the plot. The diagram below traces that chain from left to right so you can see what each stage hands to the next.

Load August 2015 datacitibike DataFrameCheck with head()time labels and valuesResample to 3Hone row per bucketPlot monthly rentalspattern across daysfirst rowschecked outputresampled table
Each stage consumes the output of the stage before it. A result that disagrees with expectation can originate in any one stage, so the chain is checked in order.

Finding Where a Prediction Diverges

When a result diverges from what you expected, the efficient move is to narrow the search instead of rereading all the code at once. Work through the stages in order, using the printed table as the cheapest checkpoint.

  1. 1
    Start with the printed table from head(), because it is the cheapest checkpoint.
  2. 2
    If the first rows already disagree with expectation, the fault lies in loading or in the pairing of labels and values.
  3. 3
    If the first rows are correct but the plot disagrees, the fault lies in a later stage, such as the resampling or the plotting step.
  • Common mistake

    Reading a value under the wrong time label

    What it looks like

    Attaching 41.0 to the 06:00 label and concluding the station was busy at 06:00.

    Why it fails

    Each value belongs to the label that starts its own interval. Under the printed order, 41.0 is the fourth row, not the third.

    Do this instead

    Read each row as a pair. Confirm the label first, then the value on the same row.

  • Common mistake

    Assuming the decimal point means fractional rentals

    What it looks like

    Believing 3.0 means three and a half rentals.

    Why it fails

    The decimal point shows that the column is stored as floating-point numbers. The quantities still count rentals.

    Do this instead

    Read the value as a whole count of rentals for that three-hour interval.

  • Common mistake

    Rereading the whole program when the plot looks wrong

    What it looks like

    Reviewing every line of code without first checking the printed first rows.

    Why it fails

    The fault could sit in loading, resampling, or plotting. Checking everything at once hides which stage actually caused the problem.

    Do this instead

    Check head() first, then the resampled table, then the plot, in that order.

  • Common mistake

    Forgetting that the plot is drawn from the resampled table, so a plot that disagrees may come from a different table than the one you printed

Practice Locating a Fault

MEDIUM

Your head() output shows the expected station's time labels, but 41.0 is printed beside the 06:00 label, and your plot looks correct for the rest of August. Which stage do you check first, and what does that tell you about where the fault is?

Hints
  • The plot is drawn from the resampled table, so if the plot is correct, the later stages are likely fine.
  • Recall that head() is the cheapest checkpoint and that the pairing of labels and values is established in the printed table.
  • Ask whether the mismatch is between a label and its value, which would point to the loading or pairing stage.

Key Takeaways

  • Loading the data gives a pandas DataFrame, and head() lets you check the first rows and their time labels before going further.
  • Resampling into three-hour intervals turns the data into one row per bucket, with one value per interval, which reveals the main trends for each day.
  • Each value belongs to the time label that starts its interval, so misreading that pairing is an early place for a wrong prediction to start.
  • When a result diverges, check each stage in order: loading, then resampling, then plotting, narrowing the search with the printed head() table first.

Related concepts

More concepts starting with W