Skip to content

Commit bf3ca08

Browse files
BUG: Block.iget not wrapping timedelta64/datetime64 (pandas-dev#31666) (pandas-dev#31688)
Co-authored-by: jbrockmendel <[email protected]>
1 parent a9d61f0 commit bf3ca08

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

doc/source/whatsnew/v1.0.1.rst

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Fixed regressions
2626
- Fixed regression in :meth:`to_datetime` when parsing non-nanosecond resolution datetimes (:issue:`31491`)
2727
- Fixed regression in :meth:`~DataFrame.to_csv` where specifying an ``na_rep`` might truncate the values written (:issue:`31447`)
2828
- Fixed regression in :class:`Categorical` construction with ``numpy.str_`` categories (:issue:`31499`)
29+
- Fixed regression in :meth:`DataFrame.loc` and :meth:`DataFrame.iloc` when selecting a row containing a single ``datetime64`` or ``timedelta64`` column (:issue:`31649`)
2930
- Fixed regression where setting :attr:`pd.options.display.max_colwidth` was not accepting negative integer. In addition, this behavior has been deprecated in favor of using ``None`` (:issue:`31532`)
3031
- Fixed regression in objTOJSON.c fix return-type warning (:issue:`31463`)
3132
- Fixed regression in :meth:`qcut` when passed a nullable integer. (:issue:`31389`)

pandas/core/internals/blocks.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import numpy as np
99

10-
from pandas._libs import NaT, algos as libalgos, lib, tslib, writers
10+
from pandas._libs import NaT, Timestamp, algos as libalgos, lib, tslib, writers
1111
from pandas._libs.index import convert_scalar
1212
import pandas._libs.internals as libinternals
1313
from pandas._libs.tslibs import Timedelta, conversion
@@ -2148,6 +2148,16 @@ def get_values(self, dtype=None):
21482148
return result.reshape(self.values.shape)
21492149
return self.values
21502150

2151+
def iget(self, key):
2152+
# GH#31649 we need to wrap scalars in Timestamp/Timedelta
2153+
# TODO: this can be removed if we ever have 2D EA
2154+
result = super().iget(key)
2155+
if isinstance(result, np.datetime64):
2156+
result = Timestamp(result)
2157+
elif isinstance(result, np.timedelta64):
2158+
result = Timedelta(result)
2159+
return result
2160+
21512161

21522162
class DatetimeBlock(DatetimeLikeBlockMixin, Block):
21532163
__slots__ = ()

pandas/tests/frame/indexing/test_indexing.py

+38
Original file line numberDiff line numberDiff line change
@@ -2276,3 +2276,41 @@ def test_transpose(self, uint64_frame):
22762276
expected = DataFrame(uint64_frame.values.T)
22772277
expected.index = ["A", "B"]
22782278
tm.assert_frame_equal(result, expected)
2279+
2280+
2281+
def test_object_casting_indexing_wraps_datetimelike():
2282+
# GH#31649, check the indexing methods all the way down the stack
2283+
df = pd.DataFrame(
2284+
{
2285+
"A": [1, 2],
2286+
"B": pd.date_range("2000", periods=2),
2287+
"C": pd.timedelta_range("1 Day", periods=2),
2288+
}
2289+
)
2290+
2291+
ser = df.loc[0]
2292+
assert isinstance(ser.values[1], pd.Timestamp)
2293+
assert isinstance(ser.values[2], pd.Timedelta)
2294+
2295+
ser = df.iloc[0]
2296+
assert isinstance(ser.values[1], pd.Timestamp)
2297+
assert isinstance(ser.values[2], pd.Timedelta)
2298+
2299+
ser = df.xs(0, axis=0)
2300+
assert isinstance(ser.values[1], pd.Timestamp)
2301+
assert isinstance(ser.values[2], pd.Timedelta)
2302+
2303+
mgr = df._data
2304+
arr = mgr.fast_xs(0)
2305+
assert isinstance(arr[1], pd.Timestamp)
2306+
assert isinstance(arr[2], pd.Timedelta)
2307+
2308+
blk = mgr.blocks[mgr._blknos[1]]
2309+
assert blk.dtype == "M8[ns]" # we got the right block
2310+
val = blk.iget((0, 0))
2311+
assert isinstance(val, pd.Timestamp)
2312+
2313+
blk = mgr.blocks[mgr._blknos[2]]
2314+
assert blk.dtype == "m8[ns]" # we got the right block
2315+
val = blk.iget((0, 0))
2316+
assert isinstance(val, pd.Timedelta)

0 commit comments

Comments
 (0)