pandas Cheatsheet

Dates and Time

Use this pandas reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Parsing Dates

import pandas as pd

# Parse a column to datetime
df["date"] = pd.to_datetime(df["date"])
df["date"] = pd.to_datetime(df["date"], format="%Y-%m-%d")       # explicit format (faster)
df["date"] = pd.to_datetime(df["date"], format="%d/%m/%Y")
df["date"] = pd.to_datetime(df["date"], errors="coerce")         # invalid → NaT
df["date"] = pd.to_datetime(df["date"], utc=True)                # localize to UTC
df["date"] = pd.to_datetime(df["date"], format="mixed")          # per-element inference

# Multiple columns → datetime
df["date"] = pd.to_datetime(df[["year", "month", "day"]])

# From Unix timestamps
pd.to_datetime(1_700_000_000, unit="s")   # seconds
pd.to_datetime(df["ts_ms"], unit="ms")    # milliseconds

# Read CSV and parse during load
df = pd.read_csv("data.csv", parse_dates=["date"])
# To combine year/month/day columns, parse after load:
df = pd.read_csv("data.csv")
df["date"] = pd.to_datetime(df[["year", "month", "day"]])

Legacy: parse_dates=[["year", "month", "day"]] (nested-list column combining) and infer_datetime_format=True were removed in pandas 3.0 — use the post-load pd.to_datetime patterns above.

Date Range Generation

pd.date_range("2024-01-01", "2024-12-31", freq="D")          # daily
pd.date_range("2024-01-01", periods=12, freq="ME")            # 12 month-ends
pd.date_range("2024-01-01", periods=4, freq="QE")             # 4 quarter-ends
pd.date_range("2024-01-01", periods=52, freq="W-MON")         # weekly, Mon
pd.date_range("09:00", "17:00", freq="h")                     # hourly
pd.date_range("2024-01-01", periods=24, freq="h", tz="UTC")   # timezone-aware

Common Frequency Aliases

AliasMeaning
"D"Calendar day
"B"Business day
"h"Hourly
"min"Minute
"s"Second
"ms"Millisecond
"us"Microsecond
"ns"Nanosecond
"W" / "W-MON"Weekly (Sunday / Monday anchor)
"ME"Month end
"MS"Month start
"QE"Quarter end
"QS"Quarter start
"YE"Year end
"YS"Year start (legacy alias "AS" deprecated in 2.2)
"BME"Business month end

.dt Accessor — Extract Date Components

s = df["date"]   # datetime64 Series

s.dt.year
s.dt.month           # 1–12
s.dt.day             # 1–31
s.dt.hour
s.dt.minute
s.dt.second
s.dt.microsecond
s.dt.nanosecond

s.dt.dayofweek       # 0=Monday … 6=Sunday
s.dt.day_name()      # "Monday", "Tuesday", …
s.dt.day_of_year     # 1–366
s.dt.isocalendar()   # DataFrame: year, week, day
s.dt.isocalendar().week  # ISO week number (dt.week was removed in 2.0)

s.dt.quarter         # 1–4
s.dt.days_in_month   # 28/29/30/31
s.dt.is_leap_year    # bool

s.dt.date            # Python date objects (object dtype)
s.dt.time            # Python time objects
s.dt.normalize()     # floor to midnight

s.dt.tz              # timezone info

.dt Rounding

s.dt.floor("h")       # round down to nearest hour
s.dt.ceil("min")      # round up to nearest minute
s.dt.round("D")       # round to nearest day

Timedeltas

# Create timedelta
td = pd.Timedelta("1 days")
td = pd.Timedelta(days=1, hours=6)
td = pd.to_timedelta(df["duration"], unit="s")   # from numeric

# Arithmetic
df["date"] + pd.Timedelta(days=7)
df["end"] - df["start"]               # returns Timedelta Series

# Timedelta components
td.days
td.seconds
td.total_seconds()

# timedelta_range
pd.timedelta_range("0 days", "7 days", freq="12h")

Timezone Handling

# Localize naive datetime to a timezone
s.dt.tz_localize("US/Eastern")
s.dt.tz_localize("UTC")
s.dt.tz_localize("America/New_York", ambiguous="NaT")   # DST ambiguity

# Convert between timezones
s.dt.tz_convert("US/Pacific")
s.dt.tz_convert("UTC")

# Remove timezone info
s.dt.tz_localize(None)

# pandas ≥ 2.0: use "UTC" aware timestamps by default to avoid performance warnings
df["date"] = pd.to_datetime(df["date"], utc=True)

Resampling Time Series

# DatetimeIndex required
df = df.set_index("date")

df.resample("ME").sum()             # monthly totals
df.resample("QE").mean()            # quarterly averages
df.resample("YE").agg({"sales": "sum", "price": "last"})
df.resample("W-MON").first()        # first value in each week
df["val"].resample("D").interpolate()  # resample + interpolate gaps

# Downsampling with custom origin
df.resample("ME", origin="start").sum()

Offset Objects and Business Days

from pandas.tseries.offsets import BDay, MonthEnd, YearEnd

today = pd.Timestamp("2024-06-15")
today + BDay(5)             # 5 business days later
today + MonthEnd(1)         # next month-end
today + YearEnd(0)          # current year-end (or next if already past)

# Business day range
pd.bdate_range("2024-01-01", "2024-01-31")

# Check if business day
pd.Timestamp("2024-06-15").isoweekday()   # 6 = Saturday

DatetimeIndex Operations

# Partial string indexing (when index is DatetimeIndex) — use .loc
df.loc["2024"]         # all of 2024
df.loc["2024-06"]      # all of June 2024
df["2024-06-01":"2024-06-30"]  # slice form still works with []

# truncate
df.truncate(before="2024-01-01", after="2024-06-30")

# shift
df.shift(1)            # shift values 1 period (freq-aware if DatetimeIndex)
df.shift(1, freq="ME") # shift index by 1 month-end

Period and PeriodIndex

p = pd.Period("2024-06", freq="M")   # Period freqs keep "M" — "ME" is only for offsets
p.start_time     # Timestamp
p.end_time       # Timestamp

pd.period_range("2024-01", "2024-12", freq="M")

# Convert between Timestamp and Period
s.dt.to_period("M")                   # Timestamp → Period (monthly)
s_period.dt.to_timestamp()            # Period → Timestamp

Common Gotchas

Timedelta arithmetic with object dtype fails — ensure the column is datetime64 first.

Partial string indexing (df.loc["2024"]) only works when the index is DatetimeIndex, not a regular column — and since pandas 2.0 it must go through .loc, not bare df["2024"].

freq="ME" (month end) replaced the old "M" alias for offsets/date_range in pandas 2.2 — but Period/to_period frequencies still use "M". Use "MS" for month start.

Mixed timezone DataFrames will fail on merge/concat — normalize to UTC first.