Time Series Data
Pandas Basics
3 min read
Published Sep 29 2025, updated Aug 17 2026
Guide Sections
Guide Comments
What is Time Series Data?
- A sequence of data points indexed (or labeled) by time.
- Examples:
- Daily stock prices
- Hourly temperature readings
- Monthly sales numbers
- In Pandas, time series data is usually represented with a DatetimeIndex.
Creating DatetimeIndex
pd.date_range() creates a sequence of datetime values to use as an index.
Example:
import pandas as pdindex = pd.date_range(start='27/10/2019 00:00:00', periods=24, freq='h')print(index)Output:
DatetimeIndex(['2019-10-27 00:00:00', '2019-10-27 01:00:00', '2019-10-27 02:00:00', ..., '2019-10-27 23:00:00'], dtype='datetime64[ns]', freq='h')It generates 24 hourly timestamps starting at midnight on Oct 27, 2019. So, it’s basically one full day, hour by hour.
Parameters Used:
start='27/10/2019 00:00:00'→ the first datetime in the range.periods=24→ number of timestamps to generate.freq='h'→ frequency = hourly.
Other Common Parameters:
end→ specify an end date instead ofperiods.freq→ frequency of steps. Examples:'B'— Business day frequency'D'— Calendar day frequency'h'— Hourly frequency'min'— Minutely frequency's'— Secondly frequency'ms'— Millisecond frequency'us'— Microsecond frequency'ns'— Nanosecond frequency'ME'— Month end frequency'MS'— Month start frequency'QE'— Quarter end frequency'QS'— Quarter start frequency'YE'— Year end frequency'YS'— Year start frequency'bh'— Business hour frequency'2D'— Every 2 days'3W'— Every 3 weeks'1H30T'— Every 1 hour and 30 minutestz→ set a timezone.
Creating DataFrame example:
import numpy as npimport pandas as pdnp.random.seed(3)df = pd.DataFrame(data={'Col1':np.random.randint(low=20,high=35,size=24) }, index=pd.date_range(start='27/10/2019 00:00:00', periods=24,freq='h'))Output:
Col12019-10-27 00:00:00 302019-10-27 01:00:00 282019-10-27 02:00:00 292019-10-27 03:00:00 232019-10-27 04:00:00 282019-10-27 05:00:00 282019-10-27 06:00:00 202019-10-27 07:00:00 252019-10-27 08:00:00 332019-10-27 09:00:00 232019-10-27 10:00:00 302019-10-27 11:00:00 312019-10-27 12:00:00 292019-10-27 13:00:00 292019-10-27 14:00:00 302019-10-27 15:00:00 252019-10-27 16:00:00 272019-10-27 17:00:00 262019-10-27 18:00:00 202019-10-27 19:00:00 242019-10-27 20:00:00 322019-10-27 21:00:00 332019-10-27 22:00:00 272019-10-27 23:00:00 34You can then access the different parts such as hour, year etc of the index. Here we add them as extra columns:
df['Hour'] = df.index.hourdf['Minute'] = df.index.minutedf['Seconds'] = df.index.seconddf['Day'] = df.index.daydf['WeekDay_number'] = df.index.weekdaydf['WeekDay_text'] = df.index.day_name()df['Month_number'] = df.index.monthdf['Month_short'] = df.index.month_name()df['Year'] = df.index.yeardf['Year-Month'] = df.index.to_period('M')# Print just the top 5 rowsprint(df.head())Output:
Col1 Hour Minute Seconds Day WeekDay_number \2019-10-27 00:00:00 30 0 0 0 27 6 2019-10-27 01:00:00 28 1 0 0 27 6 2019-10-27 02:00:00 29 2 0 0 27 6 2019-10-27 03:00:00 23 3 0 0 27 6 2019-10-27 04:00:00 28 4 0 0 27 6 WeekDay_text Month_number Month_short Year Year-Month 2019-10-27 00:00:00 Sunday 10 October 2019 2019-10 2019-10-27 01:00:00 Sunday 10 October 2019 2019-10 2019-10-27 02:00:00 Sunday 10 October 2019 2019-10 2019-10-27 03:00:00 Sunday 10 October 2019 2019-10 2019-10-27 04:00:00 Sunday 10 October 2019 2019-10Accessing date parts from non-indexed columns:
df_date = pd.DataFrame(data={'Date':pd.date_range(start='27/10/2019 00:00:00', periods=24,freq='h'), 'Col1':np.random.randint(low=20,high=35,size=24)})print(df_date.head())Creates a table with a date range that is just a standard column.
Output:
Date Col10 2019-10-27 00:00:00 311 2019-10-27 01:00:00 202 2019-10-27 02:00:00 253 2019-10-27 03:00:00 244 2019-10-27 04:00:00 34Access the date parts of the column:
df_date['Hour'] = df_date['Date'].dt.hourdf_date['Minute'] = df_date['Date'].dt.minutedf_date['Year'] = df_date['Date'].dt.yearprint(df_date.head())Add .dt before the date information when indicating the datetime data is a column.
Output:
Date Col1 Hour Minute Year0 2019-10-27 00:00:00 31 0 0 20191 2019-10-27 01:00:00 20 1 0 20192 2019-10-27 02:00:00 25 2 0 20193 2019-10-27 03:00:00 24 3 0 20194 2019-10-27 04:00:00 34 4 0 2019Converting to datetime
import pandas as pddf = pd.DataFrame({ "Date": ["2025-01-01", "2025-01-02", "2025-01-03"], "Sales": [100, 150, 200]})df["Date"] = pd.to_datetime(df["Date"])- Converts strings to datetime objects.
- Benefits: allows arithmetic, slicing, and resampling.
Setting datetime as index:
df.set_index("Date", inplace=True)print(df)Output:
SalesDate 2025-01-01 1002025-01-02 1502025-01-03 200Now df.index is a DatetimeIndex.
Accessing Time Series Data
By specific date:
df.loc["2025-01-02"]By date range:
df.loc["2025-01-01":"2025-01-02"]By year, month, or day (via string slicing):
# all data in January 2025df.loc["2025-01"]# all data in 2025df.loc["2025"] Frequency and Resampling
Pandas supports regular time intervals (daily, monthly, yearly, etc.).
# Resample daily to monthly sumdf.resample("ME").sum()# Resample monthly to daily meandf.resample("D").mean()Common frequency strings:
- Time-based
"s"→ seconds"min"→ minutes"h"→ hours"D"→ calendar day"B"→ business day- Week-based
"W"→ weekly (default Sunday end)"W-MON"→ weekly anchored to Monday- Month/Quarter/Year
"ME"→ month end"MS"→ month start"QE"→ quarter end"QS"→ quarter start"YE"→ year end"YS"→ year start- Custom
"2h"→ every 2 hours"15min"→ every 15 minutes"7D"→ every 7 days
Shifting and Lagging
Shift data forward/backward in time:
# lag by 1 daydf["Prev_Sales"] = df["Sales"].shift(1)# lead by 1 daydf["Next_Sales"] = df["Sales"].shift(-1)Useful for calculating differences or returns:
df["Sales_Change"] = df["Sales"] - df["Sales"].shift(1)# Alternative way to do the same using diff function:df["Sales_Change_Alternative"] = df["Sales"].diff(periods=1) # Or as a percentage changedf["Sales_Percent_Change"] = df["Sales"].pct_change(periods=1) Rolling and Moving Windows
Compute statistics over a rolling window:
# 3-day rolling meandf["Sales_RollingMean"] = df["Sales"].rolling(window=3).mean()# 3-day rolling sumdf["Sales_RollingSum"] = df["Sales"].rolling(3).sum()Time Series Arithmetic
Pandas allows operations on dates:
# add 1 daydf.index + pd.Timedelta(days=1)# difference from first datedf.index - df.index[0]Supports resampling, shifting, and alignment.