{"record":{"id":"bce5cbfda5de70b6","repo":"pandas-dev/pandas","slug":"std-and-sem-are-not-valid-for-perioddtype","errorCode":null,"errorMessage":"'std' and 'sem' are not valid for PeriodDtype","messagePattern":"'std' and 'sem' are not valid for PeriodDtype","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/datetimelike.py","lineNumber":1675,"sourceCode":"            min_count=min_count,\n            ngroups=ngroups,\n            comp_ids=ids,\n            mask=None,\n            **kwargs,\n        )\n\n        if op.how in op.cast_blocklist:\n            # i.e. how in [\"rank\"], since other cast_blocklist methods don't go\n            #  through cython_operation\n            return res_values\n\n        # We did a view to M8[ns] above, now we go the other direction\n        assert res_values.dtype == \"M8[ns]\"\n        if how in [\"std\", \"sem\"]:\n            from pandas.core.arrays import TimedeltaArray\n\n            if isinstance(self.dtype, PeriodDtype):\n                raise TypeError(\"'std' and 'sem' are not valid for PeriodDtype\")\n            self = cast(\"DatetimeArray | TimedeltaArray\", self)\n            new_dtype = f\"m8[{self.unit}]\"\n            res_values = res_values.view(new_dtype)\n            return TimedeltaArray._simple_new(res_values, dtype=res_values.dtype)\n\n        res_values = res_values.view(self._ndarray.dtype)\n        return self._from_backing_data(res_values)\n\n    def _groupby_quantile(\n        self,\n        *,\n        qs: npt.NDArray[np.float64],\n        interpolation: Literal[\"linear\", \"lower\", \"higher\", \"nearest\", \"midpoint\"],\n        ids: npt.NDArray[np.intp],\n        ngroups: int,\n        starts: npt.NDArray[np.int64],\n        ends: npt.NDArray[np.int64],\n    ) -> ArrayLike:","sourceCodeStart":1657,"sourceCodeEnd":1693,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/arrays/datetimelike.py#L1657-L1693","documentation":"Raised inside the std/sem branch of the groupby reduce path when self.dtype is a PeriodDtype. Standard deviation and standard error require arithmetic on magnitudes, but a Period is an ordinal label tied to a frequency, so dispersion statistics are undefined. The guard fires after the ordinal computation but before attempting to build the result.","triggerScenarios":"Calling .std() or .sem() on a PeriodIndex, PeriodArray, or a Series of Period dtype, or df.groupby('g')['period_col'].std(). Also reachable via Series.agg(['mean','std']) on a period column.","commonSituations":"Running describe()/agg() pipelines over period-encoded data (monthly reporting periods, fiscal quarters, hour-of-week periods). Treating a Period column like a datetime in a stats template.","solutions":["Drop std/sem from the aggregation for period columns.","If you need spread, convert to an ordinal integer with .astype('int64') (the period ordinal) or to Timestamp with .to_timestamp() and compute on the resulting datetime values.","Use .value_counts() or nunique() for period-distribution summaries instead."],"exampleFix":"# before\npd.period_range('2020-01','2020-05',freq='M').to_series().std()\n\n# after\nordinals = pd.period_range('2020-01','2020-05',freq='M').astype('int64')\nordinals.std()","handlingStrategy":"validation","validationCode":"if pd.api.types.is_period_dtype(s) and any(op in {'std','sem'} for op in ops):\n    raise ValueError('Period columns do not support std/sem')","typeGuard":"def is_period_column(s) -> bool:\n    return isinstance(s.dtype, pd.PeriodDtype)","tryCatchPattern":"try:\n    s.std()\nexcept TypeError as e:\n    if 'not valid for PeriodDtype' in str(e):\n        s.astype('int64').std()\n    else: raise","preventionTips":["Exclude std/sem from describe() output for period columns.","Tag period columns in metadata and route them to value_counts/nunique summaries."],"tags":["period","reduction","groupby","type-error"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}