{"record":{"id":"ccbbcadbf61bf5d9","repo":"apache/beam","slug":"pivot-is-not-supported-when-pandas-1-4-and-index-is-a","errorCode":null,"errorMessage":"pivot() is not supported when pandas<1.4 and index is a MultiIndex","messagePattern":"pivot\\(\\) is not supported when pandas<1\\.4 and index is a MultiIndex","errorType":"exception","errorClass":"WontImplementError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/dataframe/frames.py","lineNumber":3889,"sourceCode":"        col_index = pd.MultiIndex.from_product(\n          [values_in_col_index, *categories],\n          names=names\n        )\n      else:\n        # If one value provided, don't create a None level\n        names = columns\n        categories = [\n          c.categories.astype('category') for c in selected_cols.dtypes\n        ]\n        col_index = pd.MultiIndex.from_product(\n          categories,\n          names=names\n        )\n\n    # Construct row index\n    if index:\n      if PD_VERSION < (1, 4) and is_list_like(index) and len(index) > 1:\n        raise frame_base.WontImplementError(\n          \"pivot() is not supported when pandas<1.4 and index is a MultiIndex\")\n      per_partition = expressions.ComputedExpression(\n          'pivot-per-partition',\n          lambda df: df.set_index(keys=index), [self._expr],\n          preserves_partition_by=partitionings.Singleton(),\n          requires_partition_by=partitionings.Arbitrary()\n      )\n      tmp = per_partition.proxy().pivot(\n        columns=columns, values=values, **kwargs)\n      row_index = tmp.index\n    else:\n      per_partition = self._expr\n      row_index = self._expr.proxy().index\n    if PD_VERSION < (1, 4) and isinstance(row_index, pd.MultiIndex):\n      raise frame_base.WontImplementError(\n        \"pivot() is not supported when pandas<1.4 and index is a MultiIndex\")\n\n    selected_values = self._expr.proxy()[values]","sourceCodeStart":3871,"sourceCodeEnd":3907,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/dataframe/frames.py#L3871-L3907","documentation":"Beam's DataFrame.pivot throws WontImplementError when pandas is older than 1.4 and a list-like index with more than one element is given, because pivot with a MultiIndex index requires pandas>=1.4 behavior that earlier versions lack.","triggerScenarios":"Calling df.pivot(index=['a', 'b'], ...) on a DeferredDataFrame while the installed pandas version is < 1.4.","commonSituations":"Running Beam on an environment with an old pinned pandas version; upgrading pandas resolves it.","solutions":["Upgrade pandas to >= 1.4 (pip install -U 'pandas>=1.4').","Use a single index column instead of a MultiIndex index.","Restructure via set_index on the deferred frame before pivoting on one column.","Fall back to local pandas with newer version for this operation."],"exampleFix":"// before\nresult = df.pivot(index=['a', 'b'], columns='c')  # pandas 1.3\n// after\npip install 'pandas>=1.4'\nresult = df.pivot(index=['a', 'b'], columns='c')","handlingStrategy":"validation","validationCode":"import pandas as pd\ndef check_pivot_version(index):\n    if tuple(map(int, pd.__version__.split('.')[:2])) < (1, 4) and isinstance(index, (list, tuple)) and len(index) > 1:\n        raise ValueError('pivot with MultiIndex index requires pandas>=1.4')","typeGuard":"def pandas_at_least_1_4() -> bool:\n    import pandas as pd\n    return tuple(int(x) for x in pd.__version__.split('.')[:2]) >= (1, 4)","tryCatchPattern":"from apache_beam.dataframe import frame_base\ntry:\n    result = df.pivot(index=['a', 'b'], columns='c')\nexcept frame_base.WontImplementError:\n    result = df.pivot(index='a', columns='c')","preventionTips":["Pin pandas>=1.4 in requirements for Beam DataFrame workloads.","Prefer single-column pivot indices.","Log the pandas version at pipeline startup to catch env drift."],"tags":["pandas","apache-beam","dataframe","version-compatibility"],"backgroundTag":"unsupported-platform","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"}