{"record":{"id":"4c43fef85363a3fa","repo":"pandas-dev/pandas","slug":"freq-must-be-a-quarterly-frequency","errorCode":null,"errorMessage":"freq must be a quarterly frequency","messagePattern":"freq must be a quarterly frequency","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/period.py","lineNumber":1593,"sourceCode":") -> tuple[np.ndarray, BaseOffset]:\n    if hour is None:\n        hour = 0\n    if minute is None:\n        minute = 0\n    if second is None:\n        second = 0\n    if day is None:\n        day = 1\n\n    if quarter is not None:\n        if freq is None:\n            freq = to_offset(\"Q\", is_period=True)\n            base = FreqGroup.FR_QTR.value\n        else:\n            freq = to_offset(freq, is_period=True)\n            base = libperiod.freq_to_dtype_code(freq)\n            if FreqGroup.from_period_dtype_code(base) != FreqGroup.FR_QTR:\n                raise ValueError(\"freq must be a quarterly frequency\")\n\n        freqstr = freq.freqstr\n        year, quarter = _make_field_arrays(year, quarter)\n        year = _field_to_int64(year)\n        quarter = _field_to_int64(quarter)\n\n        if (quarter < 1).any() or (quarter > 4).any():\n            raise ValueError(\"Quarter must be 1 <= q <= 4\")\n\n        # Vectorized quarter_to_myear\n        mnum = MONTH_NUMBERS[parsing.get_rule_month(freqstr)] + 1\n        months = (mnum + (quarter - 1) * 3) % 12 + 1\n        years = np.where(months > mnum, year - 1, year)\n\n        length = len(years)\n        ones = np.ones(length, dtype=np.int64)\n        zeros = np.zeros(length, dtype=np.int64)\n        ordinals = libperiod.period_ordinals_from_fields(","sourceCodeStart":1575,"sourceCodeEnd":1611,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/period.py#L1575-L1611","documentation":"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.","triggerScenarios":"pd.PeriodIndex(year=..., quarter=..., freq='M') or freq='D'; passing year+quarter arrays to PeriodIndex construction with an annual/monthly/daily freq.","commonSituations":"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.","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."],"exampleFix":"# before\npd.PeriodIndex(year=2020, quarter=[1,2,3], freq='M')\n# after\npd.PeriodIndex(year=2020, quarter=[1,2,3], freq='Q')","handlingStrategy":"validation","validationCode":"from pandas.tseries.frequencies import to_offset\nfrom pandas._libs.tslibs.period import FreqGroup\nfrom pandas._libs.tslibs import libperiod\n\ndef is_quarterly(freq) -> bool:\n    base = libperiod.freq_to_dtype_code(to_offset(freq, is_period=True))\n    return FreqGroup.from_period_dtype_code(base) == FreqGroup.FR_QTR","typeGuard":"def is_quarterly_freq(freq) -> bool:\n    try:\n        return to_offset(freq, is_period=True).name.startswith('Q')\n    except Exception:\n        return False","tryCatchPattern":"try:\n    pi = pd.PeriodIndex(year=y, quarter=q, freq=freq)\nexcept ValueError as e:\n    if 'quarterly frequency' in str(e):\n        pi = pd.PeriodIndex(year=y, quarter=q, freq='Q')\n    else:\n        raise","preventionTips":["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."],"tags":["pandas","period","quarter","freq"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}