{"record":{"id":"670c08d8be53fd1f","repo":"apache/beam","slug":"robustzscore-learn-one-expected-univariate-input-but-got-s","errorCode":null,"errorMessage":"\"RobustZScore.learn_one expected univariate input, but got %s\", str(x)","messagePattern":"\"RobustZScore\\.learn_one expected univariate input, but got (.+?)\", str\\(x\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/ml/anomaly/detectors/robust_zscore.py","lineNumber":81,"sourceCode":"  .. [#] Zhao, Y., Nasrullah, Z. and Li, Z.. (2019). PyOD: A Python Toolbox for Scalable Outlier Detection. Journal of machine learning research (JMLR), 20(96), pp.1-7.\n  \"\"\"\n  # pylint: enable=line-too-long\n  SCALE_FACTOR = 0.6745\n\n  def __init__(self, mad_tracker: Optional[MadTracker] = None, **kwargs):\n    if \"threshold_criterion\" not in kwargs:\n      kwargs[\"threshold_criterion\"] = FixedThreshold(3)\n    super().__init__(**kwargs)\n    self._mad_tracker = mad_tracker or MadTracker()\n\n  def learn_one(self, x: beam.Row) -> None:\n    \"\"\"Updates the `MadTracker` with a new data point.\n\n    Args:\n      x: A `beam.Row` containing a single numerical value.\n    \"\"\"\n    if len(x.__dict__) != 1:\n      raise ValueError(\n          \"RobustZScore.learn_one expected univariate input, but got %s\",\n          str(x))\n\n    v = next(iter(x))\n    self._mad_tracker.push(v)\n\n  def score_one(self, x: beam.Row) -> Optional[float]:\n    \"\"\"Scores a data point using the Robust Z-Score.\n\n    Args:\n      x: A `beam.Row` containing a single numerical value.\n\n    Returns:\n      float | None: The Robust Z-Score.\n    \"\"\"\n    if len(x.__dict__) != 1:\n      raise ValueError(\n          \"RobustZScore.score_one expected univariate input, but got %s\",","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/ml/anomaly/detectors/robust_zscore.py#L63-L99","documentation":"RobustZScore.learn_one updates the MAD (median absolute deviation) tracker and requires x to be a beam.Row containing exactly one numerical value. A ValueError is raised when the row has any other number of fields. The robust z-score statistic is defined only for univariate input.","triggerScenarios":"Calling RobustZScore.learn_one with a beam.Row having 0 or 2+ attributes, e.g. beam.Row(x=1, y=2) or a Row built from a multi-column PCollection element.","commonSituations":"Multi-feature datasets fed directly to the detector; rows that carry an ID alongside the value; upstream schema changes adding columns to the Row.","solutions":["Project down to exactly one numeric field before learn_one: beam.Map(lambda r: beam.Row(value=r.measurement)).","Verify the row schema with len(row.__dict__) == 1 in a preceding assert/validation step.","Wrap multiple features into separate detector instances, one per feature."],"exampleFix":"// before\nbeam.Row(value=1.0, unit=\"ms\") | learn_one\n// after\nbeam.Row(value=1.0) | learn_one","handlingStrategy":"validation","validationCode":"if len(row.__dict__) != 1:\n    raise ValueError(f\"RobustZScore.learn_one requires exactly one field, got: {list(row.__dict__)}\")","typeGuard":"def is_univariate(row): return len(getattr(row, '__dict__', {})) == 1","tryCatchPattern":"try:\n    detector.learn_one(row)\nexcept ValueError as e:\n    logger.warning(\"skipping row %r: %s\", row, e)","preventionTips":["Build single-value Rows at the source with beam.Row(value=...)","One detector instance per feature","Unit-test row arity in pipeline tests"],"tags":["python","anomaly-detection","validation","univariate"],"backgroundTag":"invalid-argument-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}