pola-rs/polars · error · ValueError

DataFrame columns do not match

Error message

DataFrame columns do not match

What it means

Element-wise comparison of two DataFrames (df1 == df2, !=, <, >, ...) goes through _compare_to_other_df, which first requires identical columns: same names, same order. Since column order changes the positional pairing of the comparison, a mismatch (including mere reordering) raises ValueError instead of comparing wrong pairs.

Source

Thrown at py-polars/src/polars/dataframe/frame.py:1107

        return PolarsDataFrame(self, allow_copy=allow_copy)

    def _comp(self, other: Any, op: ComparisonOperator) -> DataFrame:
        """Compare a DataFrame with another object."""
        if isinstance(other, DataFrame):
            return self._compare_to_other_df(other, op)
        else:
            return self._compare_to_non_df(other, op)

    def _compare_to_other_df(
        self,
        other: DataFrame,
        op: ComparisonOperator,
    ) -> DataFrame:
        """Compare a DataFrame with another DataFrame."""
        if self.columns != other.columns:
            msg = "DataFrame columns do not match"
            raise ValueError(msg)
        if self.shape != other.shape:
            msg = "DataFrame dimensions do not match"
            raise ValueError(msg)

        suffix = "__POLARS_CMP_OTHER"
        other_renamed = other.select(F.all().name.suffix(suffix))
        combined = F.concat([self, other_renamed], how="horizontal", strict=True)

        if op == "eq":
            expr = [F.col(n) == F.col(f"{n}{suffix}") for n in self.columns]
        elif op == "neq":
            expr = [F.col(n) != F.col(f"{n}{suffix}") for n in self.columns]
        elif op == "gt":
            expr = [F.col(n) > F.col(f"{n}{suffix}") for n in self.columns]
        elif op == "lt":
            expr = [F.col(n) < F.col(f"{n}{suffix}") for n in self.columns]
        elif op == "gt_eq":
            expr = [F.col(n) >= F.col(f"{n}{suffix}") for n in self.columns]

View on GitHub (pinned to df599052da)

Solutions

  1. Align first: df2 = df2.select(df1.columns) then compare
  2. Rename mismatched columns before comparing: df2 = df2.rename({'old': 'new'})
  3. For order-insensitive equality testing use df1.equals(df2) or assert_frame_equal(left, right, check_column_order=False)
  4. For exact equality semantics use df1.equals(df2) which also checks dtypes

Example fix

# before
result = df1 == df2.select(['b', 'a'])  # ValueError

# after
df2 = df2.select(df1.columns)
result = df1 == df2
Defensive patterns

Strategy: validation

Validate before calling

if list(df.columns) != list(other.columns):
    other = other.select(df.columns)  # reorder/project to match
assert list(df.columns) == list(other.columns)
result = df == other

Prevention

When it happens

Trigger: df1 == df2 after df2 was built with a different column order or renamed columns; comparing a df to a filtered/selected version (df2 = df[['b', 'a']]); comparing against a join result whose column order differs.

Common situations: Test assertions comparing expected vs actual frames where construction order drifted; comparing a df to its sorted-by-column version; pipelines where one side passed through a select/rename.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/aabf73be77449e68. Report an issue: GitHub.