Skip to content

Commit c12166f

Browse files
committed
Merge pull request pandas-dev#6677 from cpcloud/index-resolvers-after-columns
ENH: define the order of resolution for index vs columns in query/eval
2 parents 80cef54 + eb88692 commit c12166f

File tree

4 files changed

+52
-2
lines changed

4 files changed

+52
-2
lines changed

doc/source/indexing.rst

+23
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,29 @@ If instead you don't want to or cannot name your index, you can use the name
784784
del old_index
785785
786786
787+
.. note::
788+
789+
If the name of your index overlaps with a column name, the column name is
790+
given precedence. For example,
791+
792+
.. ipython:: python
793+
794+
df = DataFrame({'a': randint(5, size=5)})
795+
df.index.name = 'a'
796+
df.query('a > 2') # uses the column 'a', not the index
797+
798+
You can still use the index in a query expression by using the special
799+
identifier 'index':
800+
801+
.. ipython:: python
802+
803+
df.query('index > 2')
804+
805+
If for some reason you have a column named ``index``, then you can refer to
806+
the index as ``ilevel_0`` as well, but at this point you should consider
807+
renaming your columns to something less ambiguous.
808+
809+
787810
:class:`~pandas.MultiIndex` :meth:`~pandas.DataFrame.query` Syntax
788811
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
789812

doc/source/release.rst

+2
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ API Changes
143143
- Following keywords are now acceptable for :meth:`DataFrame.plot(kind='bar')` and :meth:`DataFrame.plot(kind='barh')`.
144144
- `width`: Specify the bar width. In previous versions, static value 0.5 was passed to matplotlib and it cannot be overwritten.
145145
- `position`: Specify relative alignments for bar plot layout. From 0 (left/bottom-end) to 1(right/top-end). Default is 0.5 (center). (:issue:`6604`)
146+
- Define and document the order of column vs index names in query/eval
147+
(:issue:`6676`)
146148

147149
Deprecations
148150
~~~~~~~~~~~~

pandas/core/frame.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1855,7 +1855,7 @@ def eval(self, expr, **kwargs):
18551855
kwargs['level'] = kwargs.pop('level', 0) + 1
18561856
if resolvers is None:
18571857
index_resolvers = self._get_index_resolvers()
1858-
resolvers = index_resolvers, dict(self.iteritems())
1858+
resolvers = dict(self.iteritems()), index_resolvers
18591859
kwargs['target'] = self
18601860
kwargs['resolvers'] = kwargs.get('resolvers', ()) + resolvers
18611861
return _eval(expr, **kwargs)

pandas/tests/test_frame.py

+26-1
Original file line numberDiff line numberDiff line change
@@ -12583,7 +12583,7 @@ def setUpClass(cls):
1258312583
super(TestDataFrameQueryNumExprPandas, cls).setUpClass()
1258412584
cls.engine = 'numexpr'
1258512585
cls.parser = 'pandas'
12586-
tm.skip_if_no_ne()
12586+
tm.skip_if_no_ne(cls.engine)
1258712587

1258812588
@classmethod
1258912589
def tearDownClass(cls):
@@ -12867,6 +12867,31 @@ def test_query_undefined_local(self):
1286712867
"local variable 'c' is not defined"):
1286812868
df.query('a == @c', engine=engine, parser=parser)
1286912869

12870+
def test_index_resolvers_come_after_columns_with_the_same_name(self):
12871+
n = 1
12872+
a = np.r_[20:101:20]
12873+
12874+
df = DataFrame({'index': a, 'b': np.random.randn(a.size)})
12875+
df.index.name = 'index'
12876+
result = df.query('index > 5', engine=self.engine, parser=self.parser)
12877+
expected = df[df['index'] > 5]
12878+
tm.assert_frame_equal(result, expected)
12879+
12880+
df = DataFrame({'index': a, 'b': np.random.randn(a.size)})
12881+
result = df.query('ilevel_0 > 5', engine=self.engine, parser=self.parser)
12882+
expected = df.loc[df.index[df.index > 5]]
12883+
tm.assert_frame_equal(result, expected)
12884+
12885+
df = DataFrame({'a': a, 'b': np.random.randn(a.size)})
12886+
df.index.name = 'a'
12887+
result = df.query('a > 5', engine=self.engine, parser=self.parser)
12888+
expected = df[df.a > 5]
12889+
tm.assert_frame_equal(result, expected)
12890+
12891+
result = df.query('index > 5', engine=self.engine, parser=self.parser)
12892+
expected = df.loc[df.index[df.index > 5]]
12893+
tm.assert_frame_equal(result, expected)
12894+
1287012895

1287112896
class TestDataFrameQueryNumExprPython(TestDataFrameQueryNumExprPandas):
1287212897

0 commit comments

Comments
 (0)