{"record":{"id":"e70c5e22981db5f0","repo":"pola-rs/polars","slug":"parameters-com-span-half-life-and-alpha","errorCode":null,"errorMessage":"parameters `com`, `span`, `half_life`, and `alpha` are mutually exclusive","messagePattern":"parameters `com`, `span`, `half_life`, and `alpha` are mutually exclusive","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/expr/expr.py","lineNumber":12793,"sourceCode":"    def _skip_batch_predicate(self, schema: SchemaDict) -> Expr | None:\n        result = self._pyexpr.skip_batch_predicate(schema)\n        if result is None:\n            return None\n        return wrap_expr(result)\n\n\ndef _prepare_alpha(\n    com: float | int | None = None,\n    span: float | int | None = None,\n    half_life: float | int | None = None,\n    alpha: float | int | None = None,\n) -> float:\n    \"\"\"Normalise EWM decay specification in terms of smoothing factor 'alpha'.\"\"\"\n    if sum((param is not None) for param in (com, span, half_life, alpha)) > 1:\n        msg = (\n            \"parameters `com`, `span`, `half_life`, and `alpha` are mutually exclusive\"\n        )\n        raise ValueError(msg)\n    if com is not None:\n        if com < 0.0:\n            msg = f\"require `com` >= 0 (found {com!r})\"\n            raise ValueError(msg)\n        alpha = 1.0 / (1.0 + com)\n\n    elif span is not None:\n        if span < 1.0:\n            msg = f\"require `span` >= 1 (found {span!r})\"\n            raise ValueError(msg)\n        alpha = 2.0 / (span + 1.0)\n\n    elif half_life is not None:\n        if half_life <= 0.0:\n            msg = f\"require `half_life` > 0 (found {half_life!r})\"\n            raise ValueError(msg)\n        alpha = 1.0 - math.exp(-math.log(2.0) / half_life)\n","sourceCodeStart":12775,"sourceCodeEnd":12811,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/expr/expr.py#L12775-L12811","documentation":"_prepare_alpha normalises the exponentially-weighted decay specification used by Expr.ewm_mean (and related EWM functions). The four ways to specify decay — com, span, half_life, alpha — are mutually exclusive because each alone determines the smoothing factor; supplying more than one is contradictory and raises ValueError before any computation starts.","triggerScenarios":"pl.col('x').ewm_mean(com=0.5, span=10), ewm_mean(span=10, alpha=0.3), or any call where two of the four parameters are non-None.","commonSituations":"Copy-pasting an ewm_mean example that uses span and merging it with code that already sets com or alpha; config objects exposing all EWM knobs with several filled in; incremental edits that add a 'better' decay parameter without removing the old one.","solutions":["Keep exactly one decay parameter: com, span, half_life, or alpha.","If migrating between specifications, convert the value once (e.g. span=10 implies alpha=2/11) and pass only alpha.","Audit your config dict for EWM keys and strip all but one before calling."],"exampleFix":"# before\npl.col('x').ewm_mean(com=0.5, span=10)\n\n# after\npl.col('x').ewm_mean(span=10)","handlingStrategy":"validation","validationCode":"params = {'com': com, 'span': span, 'half_life': half_life, 'alpha': alpha}\nprovided = [k for k, v in params.items() if v is not None]\nassert len(provided) == 1, f'exactly one decay param required, got {provided}'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Model decay as one choice in config (an enum or oneof), not four optional numbers.","Recall pandas ewm has the same exclusivity rule — porting code should already satisfy it."],"tags":["validation","polars","expression","ewm","statistics"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}