pandas-dev/pandas · error · ValueError
freq must be a quarterly frequency
Error message
freq must be a quarterly frequency
What it means
Raised by _range_from_fields when quarter is supplied but freq resolves to a non-quarterly frequency (FreqGroup != FR_QTR). Quarter-based period construction is only meaningful for quarterly frequencies because the quarter field maps onto a 3-month window.
Source
Thrown at pandas/core/arrays/period.py:1593
) -> tuple[np.ndarray, BaseOffset]:
if hour is None:
hour = 0
if minute is None:
minute = 0
if second is None:
second = 0
if day is None:
day = 1
if quarter is not None:
if freq is None:
freq = to_offset("Q", is_period=True)
base = FreqGroup.FR_QTR.value
else:
freq = to_offset(freq, is_period=True)
base = libperiod.freq_to_dtype_code(freq)
if FreqGroup.from_period_dtype_code(base) != FreqGroup.FR_QTR:
raise ValueError("freq must be a quarterly frequency")
freqstr = freq.freqstr
year, quarter = _make_field_arrays(year, quarter)
year = _field_to_int64(year)
quarter = _field_to_int64(quarter)
if (quarter < 1).any() or (quarter > 4).any():
raise ValueError("Quarter must be 1 <= q <= 4")
# Vectorized quarter_to_myear
mnum = MONTH_NUMBERS[parsing.get_rule_month(freqstr)] + 1
months = (mnum + (quarter - 1) * 3) % 12 + 1
years = np.where(months > mnum, year - 1, year)
length = len(years)
ones = np.ones(length, dtype=np.int64)
zeros = np.zeros(length, dtype=np.int64)
ordinals = libperiod.period_ordinals_from_fields(View on GitHub (pinned to 3b7651241d)
Solutions
- Use freq='Q' or a quarterly anchored variant like 'Q-DEC', 'Q-JAN'.
- If you have year+month data instead, pass month= rather than quarter= with freq='M'.
- Drop the quarter argument and supply month directly for non-quarterly freqs.
Example fix
# before pd.PeriodIndex(year=2020, quarter=[1,2,3], freq='M') # after pd.PeriodIndex(year=2020, quarter=[1,2,3], freq='Q')
Defensive patterns
Strategy: validation
Validate before calling
from pandas.tseries.frequencies import to_offset
from pandas._libs.tslibs.period import FreqGroup
from pandas._libs.tslibs import libperiod
def is_quarterly(freq) -> bool:
base = libperiod.freq_to_dtype_code(to_offset(freq, is_period=True))
return FreqGroup.from_period_dtype_code(base) == FreqGroup.FR_QTR Type guard
def is_quarterly_freq(freq) -> bool:
try:
return to_offset(freq, is_period=True).name.startswith('Q')
except Exception:
return False Try / catch
try:
pi = pd.PeriodIndex(year=y, quarter=q, freq=freq)
except ValueError as e:
if 'quarterly frequency' in str(e):
pi = pd.PeriodIndex(year=y, quarter=q, freq='Q')
else:
raise Prevention
- Pair year+quarter only with freq='Q' (or 'Q-DEC' / 'Q-JAN' anchors).
- For monthly data use month=, not quarter=.
- Document the freq assumption at the call site.
When it happens
Trigger: pd.PeriodIndex(year=..., quarter=..., freq='M') or freq='D'; passing year+quarter arrays to PeriodIndex construction with an annual/monthly/daily freq.
Common situations: Treating quarter as a generic field independent of freq; passing an offset that is a multiple of a quarter (e.g. '2Q') without realizing the group check still passes — but passing 'A', 'M', 'W' fails.
Related errors
- Invalid dtype {dtype} for PeriodArray
- dtype is not specified and cannot be inferred
- Not supported to convert PeriodArray to array with different
- Cannot add or subtract timedelta64[ns] dtype from {self.dtyp
- Cannot add/subtract timedelta-like from PeriodArray that is
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/4c43fef85363a3fa.
Report an issue: GitHub.