From 6ab128c9c14284a519ccf928b0172394ad6ad463 Mon Sep 17 00:00:00 2001 From: David Carvalho Date: Sun, 23 Mar 2025 20:32:35 +0000 Subject: [PATCH 1/2] Fix #60494: query doesn't work on DataFrame integer column names --- doc/source/whatsnew/v3.0.0.rst | 1 + pandas/core/frame.py | 6 ++++++ pandas/tests/frame/test_query_eval.py | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 25c26253e687b..469af1a7921ab 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -826,6 +826,7 @@ Other - Bug in :meth:`DataFrame.eval` and :meth:`DataFrame.query` which did not allow to use ``tan`` function. (:issue:`55091`) - Bug in :meth:`DataFrame.query` where using duplicate column names led to a ``TypeError``. (:issue:`59950`) - Bug in :meth:`DataFrame.query` which raised an exception or produced incorrect results when expressions contained backtick-quoted column names containing the hash character ``#``, backticks, or characters that fall outside the ASCII range (U+0001..U+007F). (:issue:`59285`) (:issue:`49633`) +- Bug in :meth:`DataFrame.query` which raised an exception when querying integer column names using backticks. (:issue:`60494`) - Bug in :meth:`DataFrame.shift` where passing a ``freq`` on a DataFrame with no columns did not shift the index correctly. (:issue:`60102`) - Bug in :meth:`DataFrame.sort_index` when passing ``axis="columns"`` and ``ignore_index=True`` and ``ascending=False`` not returning a :class:`RangeIndex` columns (:issue:`57293`) - Bug in :meth:`DataFrame.transform` that was returning the wrong order unless the index was monotonically increasing. (:issue:`57069`) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index c862b7dbaf973..c29581c8bfb46 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -4790,6 +4790,12 @@ def eval(self, expr: str, *, inplace: bool = False, **kwargs) -> Any | None: inplace = validate_bool_kwarg(inplace, "inplace") kwargs["level"] = kwargs.pop("level", 0) + 1 index_resolvers = self._get_index_resolvers() + + if any(isinstance(col, int) for col in self.columns): + self = self.rename( + columns={col: f"{col}" for col in self.columns if isinstance(col, int)} + ) + column_resolvers = self._get_cleaned_column_resolvers() resolvers = column_resolvers, index_resolvers if "target" not in kwargs: diff --git a/pandas/tests/frame/test_query_eval.py b/pandas/tests/frame/test_query_eval.py index 375b9b00a4988..f93105498ac79 100644 --- a/pandas/tests/frame/test_query_eval.py +++ b/pandas/tests/frame/test_query_eval.py @@ -1345,6 +1345,11 @@ def test_start_with_spaces(self, df): expect = df[" A"] + df[" "] tm.assert_series_equal(res, expect) + def test_ints(self, df): + res = df.query("`1` == 7") + expect = df[df[1] == 7] + tm.assert_frame_equal(res, expect) + def test_lots_of_operators_string(self, df): res = df.query("` &^ :!€$?(} > <++*'' ` > 4") expect = df[df[" &^ :!€$?(} > <++*'' "] > 4] From 4c0d2c8b22dbba9ce5828e3e1069de557e33f7d5 Mon Sep 17 00:00:00 2001 From: David Carvalho Date: Tue, 1 Apr 2025 16:24:30 +0100 Subject: [PATCH 2/2] fix: removed line that ignores an integer column name from _get_cleaned_column_resolvers Also removed the changes from the previous commit, which converted integer column names to strings --- pandas/core/frame.py | 6 ------ pandas/core/generic.py | 1 - 2 files changed, 7 deletions(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index c29581c8bfb46..c862b7dbaf973 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -4790,12 +4790,6 @@ def eval(self, expr: str, *, inplace: bool = False, **kwargs) -> Any | None: inplace = validate_bool_kwarg(inplace, "inplace") kwargs["level"] = kwargs.pop("level", 0) + 1 index_resolvers = self._get_index_resolvers() - - if any(isinstance(col, int) for col in self.columns): - self = self.rename( - columns={col: f"{col}" for col in self.columns if isinstance(col, int)} - ) - column_resolvers = self._get_cleaned_column_resolvers() resolvers = column_resolvers, index_resolvers if "target" not in kwargs: diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 0c3f535df9ce2..8b6803ccb0ec1 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -612,7 +612,6 @@ def _get_cleaned_column_resolvers(self) -> dict[Hashable, Series]: v, copy=False, index=self.index, name=k, dtype=dtype ).__finalize__(self) for k, v, dtype in zip(self.columns, self._iter_column_arrays(), dtypes) - if not isinstance(k, int) } @final