Skip to content

DEPR: row-based indexing in DataFrame.__getitem__ #31334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
8 changes: 8 additions & 0 deletions doc/source/user_guide/timeseries.rst
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ partial string selection is a form of label slicing, the endpoints **will be** i
would include matching times on an included date:

.. ipython:: python
:okwarning:

dft = pd.DataFrame(np.random.randn(100000, 1), columns=['A'],
index=pd.date_range('20130101', periods=100000, freq='T'))
Expand Down Expand Up @@ -677,6 +678,7 @@ If index resolution is second, then the minute-accurate timestamp gives a
If the timestamp string is treated as a slice, it can be used to index ``DataFrame`` with ``[]`` as well.

.. ipython:: python
:okwarning:

dft_minute = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the whitespace alignment is off here (:okwarning: and dft_minute... should be vertically aligned)

index=series_minute.index)
Expand All @@ -689,7 +691,11 @@ If the timestamp string is treated as a slice, it can be used to index ``DataFra

To *always* have unambiguous selection, whether the row is treated as a slice or a single selection, use ``.loc``.

As of version 1.1.0, row-based indexing is deprecated. Users should always use ``.loc``
for label-based row indexing.

.. ipython:: python
:okwarning:
Copy link
Contributor

@TomAugspurger TomAugspurger Jan 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this cause a warning? It's using loc so I wouldn't think it would.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i took the kitchen-sink approach to getting the docbuild passing, will figure out which of these can be trimmed away


dft_minute.loc['2011-12-31 23:59']

Expand Down Expand Up @@ -1968,6 +1974,7 @@ You can pass in dates and strings to ``Series`` and ``DataFrame`` with ``PeriodI
Passing a string representing a lower frequency than ``PeriodIndex`` returns partial sliced data.

.. ipython:: python
:okwarning:

ps['2011']

Expand All @@ -1982,6 +1989,7 @@ Passing a string representing a lower frequency than ``PeriodIndex`` returns par
As with ``DatetimeIndex``, the endpoints will be included in the result. The example below slices data starting from 10:00 to 11:59.

.. ipython:: python
:okwarning:

dfp['2013-01-01 10H':'2013-01-01 11H']

Expand Down
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.11.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ Enhancements
- You can now select with a string from a DataFrame with a datelike index, in a similar way to a Series (:issue:`3070`)

.. ipython:: python
:okwarning:

idx = pd.date_range("2001-10-1", periods=5, freq='M')
ts = pd.Series(np.random.rand(len(idx)), index=idx)
Expand Down
14 changes: 14 additions & 0 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -2776,6 +2776,13 @@ def __getitem__(self, key):
if indexer is not None:
# either we have a slice or we have a string that can be converted
# to a slice for partial-string date indexing
if not isinstance(key, slice):
warnings.warn(
"row-based slicing on a DataFrame is deprecated and will "
"raise in a future version. Use `df.loc[key]` instead.",
FutureWarning,
stacklevel=2,
)
return self._slice(indexer, axis=0)

# Do we have a (boolean) DataFrame?
Expand Down Expand Up @@ -2926,6 +2933,13 @@ def __setitem__(self, key, value):
if indexer is not None:
# either we have a slice or we have a string that can be converted
# to a slice for partial-string date indexing
if not isinstance(key, slice):
warnings.warn(
"row-based slicing on a DataFrame is deprecated and will "
"raise in a future version. Use `df.loc[key]` instead.",
FutureWarning,
stacklevel=2,
)
return self._setitem_slice(indexer, value)

if isinstance(key, DataFrame) or getattr(key, "ndim", None) == 2:
Expand Down
8 changes: 6 additions & 2 deletions pandas/core/indexing.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Hashable, List, Tuple, Union
from typing import TYPE_CHECKING, Hashable, List, Tuple, Union

import numpy as np

Expand Down Expand Up @@ -29,6 +29,10 @@
from pandas.core.indexes.api import Index
from pandas.core.indexes.base import InvalidIndexError

if TYPE_CHECKING:
from pandas import DataFrame


# "null slice"
_NS = slice(None, None)

Expand Down Expand Up @@ -2167,7 +2171,7 @@ def _tuplify(ndim: int, loc: Hashable) -> Tuple[Union[Hashable, slice], ...]:
return tuple(_tup)


def convert_to_index_sliceable(obj, key):
def convert_to_index_sliceable(obj: "DataFrame", key):
"""
If we are index sliceable, then return my slicer, otherwise return None.
"""
Expand Down
3 changes: 2 additions & 1 deletion pandas/tests/indexes/datetimes/test_partial_slicing.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,8 @@ def test_partial_slicing_dataframe(self):
tm.assert_series_equal(result, expected)

# Frame should return slice as well
result = df[ts_string]
with tm.assert_produces_warning(FutureWarning):
result = df[ts_string]
expected = df[theslice]
tm.assert_frame_equal(result, expected)

Expand Down
8 changes: 6 additions & 2 deletions pandas/tests/series/indexing/test_datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,9 @@ def test_indexing():
expected.name = "A"

df = DataFrame(dict(A=ts))
result = df["2001"]["A"]
with tm.assert_produces_warning(FutureWarning):
ser = df["2001"]
result = ser["A"]
tm.assert_series_equal(expected, result)

# setting
Expand All @@ -651,7 +653,9 @@ def test_indexing():

df.loc["2001", "A"] = 1

result = df["2001"]["A"]
with tm.assert_produces_warning(FutureWarning):
ser = df["2001"]
result = ser["A"]
tm.assert_series_equal(expected, result)

# GH3546 (not including times on the last day)
Expand Down