Skip to content

Commit 7e1799b

Browse files
jbrockmendelluckyvs1
authored andcommitted
DEPR: datetimelike.astype(int) (pandas-dev#38544)
1 parent 801e7c7 commit 7e1799b

File tree

15 files changed

+122
-39
lines changed

15 files changed

+122
-39
lines changed

doc/source/whatsnew/v1.3.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ Deprecations
146146
~~~~~~~~~~~~
147147
- Deprecating allowing scalars passed to the :class:`Categorical` constructor (:issue:`38433`)
148148
- Deprecated allowing subclass-specific keyword arguments in the :class:`Index` constructor, use the specific subclass directly instead (:issue:`14093`,:issue:`21311`,:issue:`22315`,:issue:`26974`)
149+
- Deprecated ``astype`` of datetimelike (``timedelta64[ns]``, ``datetime64[ns]``, ``Datetime64TZDtype``, ``PeriodDtype``) to integer dtypes, use ``values.view(...)`` instead (:issue:`38544`)
149150
-
150151
-
151152

pandas/core/arrays/datetimelike.py

+8
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,14 @@ def astype(self, dtype, copy=True):
352352
elif is_integer_dtype(dtype):
353353
# we deliberately ignore int32 vs. int64 here.
354354
# See https://github.com/pandas-dev/pandas/issues/24381 for more.
355+
warnings.warn(
356+
f"casting {self.dtype} values to int64 with .astype(...) is "
357+
"deprecated and will raise in a future version. "
358+
"Use .view(...) instead.",
359+
FutureWarning,
360+
stacklevel=3,
361+
)
362+
355363
values = self.asi8
356364

357365
if is_unsigned_integer_dtype(dtype):

pandas/core/dtypes/cast.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""
22
Routines for casting.
33
"""
4-
54
from contextlib import suppress
65
from datetime import datetime, timedelta
76
from typing import (
@@ -17,6 +16,7 @@
1716
Type,
1817
Union,
1918
)
19+
import warnings
2020

2121
import numpy as np
2222

@@ -997,6 +997,14 @@ def astype_nansafe(
997997

998998
elif is_datetime64_dtype(arr):
999999
if dtype == np.int64:
1000+
warnings.warn(
1001+
f"casting {arr.dtype} values to int64 with .astype(...) "
1002+
"is deprecated and will raise in a future version. "
1003+
"Use .view(...) instead.",
1004+
FutureWarning,
1005+
# stacklevel chosen to be correct when reached via Series.astype
1006+
stacklevel=7,
1007+
)
10001008
if isna(arr).any():
10011009
raise ValueError("Cannot convert NaT values to integer")
10021010
return arr.view(dtype)
@@ -1009,6 +1017,14 @@ def astype_nansafe(
10091017

10101018
elif is_timedelta64_dtype(arr):
10111019
if dtype == np.int64:
1020+
warnings.warn(
1021+
f"casting {arr.dtype} values to int64 with .astype(...) "
1022+
"is deprecated and will raise in a future version. "
1023+
"Use .view(...) instead.",
1024+
FutureWarning,
1025+
# stacklevel chosen to be correct when reached via Series.astype
1026+
stacklevel=7,
1027+
)
10121028
if isna(arr).any():
10131029
raise ValueError("Cannot convert NaT values to integer")
10141030
return arr.view(dtype)

pandas/tests/arrays/test_datetimes.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,18 @@ def test_astype_copies(self, dtype, other):
184184
@pytest.mark.parametrize("dtype", [int, np.int32, np.int64, "uint32", "uint64"])
185185
def test_astype_int(self, dtype):
186186
arr = DatetimeArray._from_sequence([pd.Timestamp("2000"), pd.Timestamp("2001")])
187-
result = arr.astype(dtype)
187+
with tm.assert_produces_warning(FutureWarning):
188+
# astype(int..) deprecated
189+
result = arr.astype(dtype)
188190

189191
if np.dtype(dtype).kind == "u":
190192
expected_dtype = np.dtype("uint64")
191193
else:
192194
expected_dtype = np.dtype("int64")
193-
expected = arr.astype(expected_dtype)
195+
196+
with tm.assert_produces_warning(FutureWarning):
197+
# astype(int..) deprecated
198+
expected = arr.astype(expected_dtype)
194199

195200
assert result.dtype == expected_dtype
196201
tm.assert_numpy_array_equal(result, expected)

pandas/tests/arrays/test_period.py

+14-4
Original file line numberDiff line numberDiff line change
@@ -123,26 +123,36 @@ def test_astype(dtype):
123123
# We choose to ignore the sign and size of integers for
124124
# Period/Datetime/Timedelta astype
125125
arr = period_array(["2000", "2001", None], freq="D")
126-
result = arr.astype(dtype)
126+
with tm.assert_produces_warning(FutureWarning):
127+
# astype(int..) deprecated
128+
result = arr.astype(dtype)
127129

128130
if np.dtype(dtype).kind == "u":
129131
expected_dtype = np.dtype("uint64")
130132
else:
131133
expected_dtype = np.dtype("int64")
132-
expected = arr.astype(expected_dtype)
134+
135+
with tm.assert_produces_warning(FutureWarning):
136+
# astype(int..) deprecated
137+
expected = arr.astype(expected_dtype)
133138

134139
assert result.dtype == expected_dtype
135140
tm.assert_numpy_array_equal(result, expected)
136141

137142

138143
def test_astype_copies():
139144
arr = period_array(["2000", "2001", None], freq="D")
140-
result = arr.astype(np.int64, copy=False)
145+
with tm.assert_produces_warning(FutureWarning):
146+
# astype(int..) deprecated
147+
result = arr.astype(np.int64, copy=False)
148+
141149
# Add the `.base`, since we now use `.asi8` which returns a view.
142150
# We could maybe override it in PeriodArray to return ._data directly.
143151
assert result.base is arr._data
144152

145-
result = arr.astype(np.int64, copy=True)
153+
with tm.assert_produces_warning(FutureWarning):
154+
# astype(int..) deprecated
155+
result = arr.astype(np.int64, copy=True)
146156
assert result is not arr._data
147157
tm.assert_numpy_array_equal(result, arr._data.view("i8"))
148158

pandas/tests/arrays/test_timedeltas.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,18 @@ def test_from_sequence_dtype(self):
8282
@pytest.mark.parametrize("dtype", [int, np.int32, np.int64, "uint32", "uint64"])
8383
def test_astype_int(self, dtype):
8484
arr = TimedeltaArray._from_sequence([Timedelta("1H"), Timedelta("2H")])
85-
result = arr.astype(dtype)
85+
with tm.assert_produces_warning(FutureWarning):
86+
# astype(int..) deprecated
87+
result = arr.astype(dtype)
8688

8789
if np.dtype(dtype).kind == "u":
8890
expected_dtype = np.dtype("uint64")
8991
else:
9092
expected_dtype = np.dtype("int64")
91-
expected = arr.astype(expected_dtype)
93+
94+
with tm.assert_produces_warning(FutureWarning):
95+
# astype(int..) deprecated
96+
expected = arr.astype(expected_dtype)
9297

9398
assert result.dtype == expected_dtype
9499
tm.assert_numpy_array_equal(result, expected)

pandas/tests/dtypes/test_common.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,9 @@ def test_astype_nansafe(val, typ):
719719

720720
msg = "Cannot convert NaT values to integer"
721721
with pytest.raises(ValueError, match=msg):
722-
astype_nansafe(arr, dtype=typ)
722+
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
723+
# datetimelike astype(int64) deprecated
724+
astype_nansafe(arr, dtype=typ)
723725

724726

725727
@pytest.mark.parametrize("from_type", [np.datetime64, np.timedelta64])

pandas/tests/indexes/datetimes/methods/test_astype.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ def test_astype(self):
2929
)
3030
tm.assert_index_equal(result, expected)
3131

32-
result = idx.astype(int)
32+
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
33+
result = idx.astype(int)
3334
expected = Int64Index(
3435
[1463356800000000000] + [-9223372036854775808] * 3,
3536
dtype=np.int64,
@@ -38,7 +39,8 @@ def test_astype(self):
3839
tm.assert_index_equal(result, expected)
3940

4041
rng = date_range("1/1/2000", periods=10, name="idx")
41-
result = rng.astype("i8")
42+
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
43+
result = rng.astype("i8")
4244
tm.assert_index_equal(result, Index(rng.asi8, name="idx"))
4345
tm.assert_numpy_array_equal(result.values, rng.asi8)
4446

@@ -48,9 +50,9 @@ def test_astype_uint(self):
4850
np.array([946684800000000000, 946771200000000000], dtype="uint64"),
4951
name="idx",
5052
)
51-
52-
tm.assert_index_equal(arr.astype("uint64"), expected)
53-
tm.assert_index_equal(arr.astype("uint32"), expected)
53+
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
54+
tm.assert_index_equal(arr.astype("uint64"), expected)
55+
tm.assert_index_equal(arr.astype("uint32"), expected)
5456

5557
def test_astype_with_tz(self):
5658

pandas/tests/indexes/interval/test_astype.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,13 @@ def index(self, request):
197197
@pytest.mark.parametrize("subtype", ["int64", "uint64"])
198198
def test_subtype_integer(self, index, subtype):
199199
dtype = IntervalDtype(subtype)
200-
result = index.astype(dtype)
201-
expected = IntervalIndex.from_arrays(
202-
index.left.astype(subtype), index.right.astype(subtype), closed=index.closed
203-
)
200+
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
201+
result = index.astype(dtype)
202+
expected = IntervalIndex.from_arrays(
203+
index.left.astype(subtype),
204+
index.right.astype(subtype),
205+
closed=index.closed,
206+
)
204207
tm.assert_index_equal(result, expected)
205208

206209
def test_subtype_float(self, index):

pandas/tests/indexes/interval/test_constructors.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,21 @@ def test_constructor(self, constructor, breaks, closed, name):
7272
)
7373
def test_constructor_dtype(self, constructor, breaks, subtype):
7474
# GH 19262: conversion via dtype parameter
75-
expected_kwargs = self.get_kwargs_from_breaks(breaks.astype(subtype))
75+
warn = None
76+
if subtype == "int64" and breaks.dtype.kind in ["M", "m"]:
77+
# astype(int64) deprecated
78+
warn = FutureWarning
79+
80+
with tm.assert_produces_warning(warn, check_stacklevel=False):
81+
expected_kwargs = self.get_kwargs_from_breaks(breaks.astype(subtype))
7682
expected = constructor(**expected_kwargs)
7783

7884
result_kwargs = self.get_kwargs_from_breaks(breaks)
7985
iv_dtype = IntervalDtype(subtype)
8086
for dtype in (iv_dtype, str(iv_dtype)):
81-
result = constructor(dtype=dtype, **result_kwargs)
87+
with tm.assert_produces_warning(warn, check_stacklevel=False):
88+
89+
result = constructor(dtype=dtype, **result_kwargs)
8290
tm.assert_index_equal(result, expected)
8391

8492
@pytest.mark.filterwarnings("ignore:Passing keywords other:FutureWarning")

pandas/tests/indexes/period/methods/test_astype.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ def test_astype_conversion(self):
3737
)
3838
tm.assert_index_equal(result, expected)
3939

40-
result = idx.astype(np.int64)
40+
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
41+
result = idx.astype(np.int64)
4142
expected = Int64Index(
4243
[16937] + [-9223372036854775808] * 3, dtype=np.int64, name="idx"
4344
)
@@ -48,15 +49,17 @@ def test_astype_conversion(self):
4849
tm.assert_index_equal(result, expected)
4950

5051
idx = period_range("1990", "2009", freq="A", name="idx")
51-
result = idx.astype("i8")
52+
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
53+
result = idx.astype("i8")
5254
tm.assert_index_equal(result, Index(idx.asi8, name="idx"))
5355
tm.assert_numpy_array_equal(result.values, idx.asi8)
5456

5557
def test_astype_uint(self):
5658
arr = period_range("2000", periods=2, name="idx")
5759
expected = UInt64Index(np.array([10957, 10958], dtype="uint64"), name="idx")
58-
tm.assert_index_equal(arr.astype("uint64"), expected)
59-
tm.assert_index_equal(arr.astype("uint32"), expected)
60+
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
61+
tm.assert_index_equal(arr.astype("uint64"), expected)
62+
tm.assert_index_equal(arr.astype("uint32"), expected)
6063

6164
def test_astype_object(self):
6265
idx = PeriodIndex([], freq="M")

pandas/tests/indexes/test_common.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,14 @@ def test_astype_preserves_name(self, index, dtype):
341341
else:
342342
index.name = "idx"
343343

344+
warn = None
345+
if dtype in ["int64", "uint64"]:
346+
if needs_i8_conversion(index.dtype):
347+
warn = FutureWarning
344348
try:
345349
# Some of these conversions cannot succeed so we use a try / except
346-
result = index.astype(dtype)
350+
with tm.assert_produces_warning(warn, check_stacklevel=False):
351+
result = index.astype(dtype)
347352
except (ValueError, TypeError, NotImplementedError, SystemError):
348353
return
349354

pandas/tests/indexes/timedeltas/methods/test_astype.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ def test_astype(self):
5555
)
5656
tm.assert_index_equal(result, expected)
5757

58-
result = idx.astype(int)
58+
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
59+
result = idx.astype(int)
5960
expected = Int64Index(
6061
[100000000000000] + [-9223372036854775808] * 3, dtype=np.int64, name="idx"
6162
)
@@ -66,7 +67,8 @@ def test_astype(self):
6667
tm.assert_index_equal(result, expected)
6768

6869
rng = timedelta_range("1 days", periods=10)
69-
result = rng.astype("i8")
70+
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
71+
result = rng.astype("i8")
7072
tm.assert_index_equal(result, Index(rng.asi8))
7173
tm.assert_numpy_array_equal(rng.asi8, result.values)
7274

@@ -75,9 +77,9 @@ def test_astype_uint(self):
7577
expected = pd.UInt64Index(
7678
np.array([3600000000000, 90000000000000], dtype="uint64")
7779
)
78-
79-
tm.assert_index_equal(arr.astype("uint64"), expected)
80-
tm.assert_index_equal(arr.astype("uint32"), expected)
80+
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
81+
tm.assert_index_equal(arr.astype("uint64"), expected)
82+
tm.assert_index_equal(arr.astype("uint32"), expected)
8183

8284
def test_astype_timedelta64(self):
8385
# GH 13149, GH 13209

pandas/tests/internals/test_internals.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,9 @@ def test_astype(self, t):
454454
# coerce all
455455
mgr = create_mgr("c: f4; d: f2; e: f8")
456456

457+
warn = FutureWarning if t == "int64" else None
458+
# datetimelike.astype(int64) deprecated
459+
457460
t = np.dtype(t)
458461
tmgr = mgr.astype(t)
459462
assert tmgr.iget(0).dtype.type == t
@@ -464,7 +467,8 @@ def test_astype(self, t):
464467
mgr = create_mgr("a,b: object; c: bool; d: datetime; e: f4; f: f2; g: f8")
465468

466469
t = np.dtype(t)
467-
tmgr = mgr.astype(t, errors="ignore")
470+
with tm.assert_produces_warning(warn):
471+
tmgr = mgr.astype(t, errors="ignore")
468472
assert tmgr.iget(2).dtype.type == t
469473
assert tmgr.iget(4).dtype.type == t
470474
assert tmgr.iget(5).dtype.type == t

0 commit comments

Comments
 (0)