Skip to content

Commit 291d30f

Browse files
author
Chris Bertinato
committed
DEPR: Deprecate box kwarg for to_timedelta and to_datetime
1 parent 85572de commit 291d30f

File tree

8 files changed

+126
-60
lines changed

8 files changed

+126
-60
lines changed

doc/source/whatsnew/v0.24.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,7 @@ Deprecations
13261326
- Passing an integer to :meth:`Series.fillna` and :meth:`DataFrame.fillna` with ``timedelta64[ns]`` dtypes is deprecated, will raise ``TypeError`` in a future version. Use ``obj.fillna(pd.Timedelta(...))`` instead (:issue:`24694`)
13271327
- ``Series.cat.categorical``, ``Series.cat.name`` and ``Sersies.cat.index`` have been deprecated. Use the attributes on ``Series.cat`` or ``Series`` directly. (:issue:`24751`).
13281328
- Passing a dtype without a precision like ``np.dtype('datetime64')`` or ``timedelta64`` to :class:`Index`, :class:`DatetimeIndex` and :class:`TimedeltaIndex` is now deprecated. Use the nanosecond-precision dtype instead (:issue:`24753`).
1329+
- The functions :func:`pandas.to_datetime` and :func:`pandas.to_timedelta` have deprecated the ``box`` keyword. Use :attr:`Series.values` and :meth:`Timestamp.to_datetime64`/:meth:`Timedelta.to_timedelta64` instead to get an ndarray of values or ``numpy.timestamp64``/``numpy.timedelta64``, respectively (:issue:`24416`).
13291330

13301331
.. _whatsnew_0240.deprecations.datetimelike_int_ops:
13311332

pandas/core/dtypes/cast.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -794,10 +794,10 @@ def soft_convert_objects(values, datetime=True, numeric=True, timedelta=True,
794794
# Immediate return if coerce
795795
if datetime:
796796
from pandas import to_datetime
797-
return to_datetime(values, errors='coerce', box=False)
797+
return to_datetime(values, errors='coerce').to_numpy()
798798
elif timedelta:
799799
from pandas import to_timedelta
800-
return to_timedelta(values, errors='coerce', box=False)
800+
return to_timedelta(values, errors='coerce').to_numpy()
801801
elif numeric:
802802
from pandas import to_numeric
803803
return to_numeric(values, errors='coerce')

pandas/core/indexes/datetimelike.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,12 @@ def asobject(self):
300300
return self.astype(object)
301301

302302
def _convert_tolerance(self, tolerance, target):
303-
tolerance = np.asarray(to_timedelta(tolerance, box=False))
303+
tolerance = to_timedelta(tolerance)
304+
if isinstance(tolerance, ABCIndexClass):
305+
tolerance = tolerance.to_numpy()
306+
else:
307+
tolerance = np.asarray(tolerance.to_timedelta64())
308+
304309
if target.size != tolerance.size and tolerance.size > 1:
305310
raise ValueError('list-like tolerance size must match '
306311
'target index size')

pandas/core/tools/datetimes.py

+9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
from pandas import compat
2121
from pandas.core import algorithms
2222

23+
from pandas.util._decorators import deprecate_kwarg
24+
2325

2426
def _guess_datetime_format_for_array(arr, **kwargs):
2527
# Try to guess the format based on the first non-NaN element
@@ -398,6 +400,7 @@ def _adjust_to_origin(arg, origin, unit):
398400
return arg
399401

400402

403+
@deprecate_kwarg(old_arg_name='box', new_arg_name=None)
401404
def to_datetime(arg, errors='raise', dayfirst=False, yearfirst=False,
402405
utc=None, box=True, format=None, exact=True,
403406
unit=None, infer_datetime_format=False, origin='unix',
@@ -444,6 +447,12 @@ def to_datetime(arg, errors='raise', dayfirst=False, yearfirst=False,
444447
445448
- If True returns a DatetimeIndex or Index-like object
446449
- If False returns ndarray of values.
450+
451+
.. deprecated:: 0.24.0
452+
Use :meth:`.to_numpy` or :meth:`Timestamp.to_datetime64`
453+
instead to get an ndarray of values or numpy.datetime64,
454+
respectively.
455+
447456
format : string, default None
448457
strftime to parse time, eg "%d/%m/%Y", note that "%f" will parse
449458
all the way up to nanoseconds.

pandas/core/tools/timedeltas.py

+9
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414

1515
from pandas.core.arrays.timedeltas import sequence_to_td64ns
1616

17+
from pandas.util._decorators import deprecate_kwarg
1718

19+
20+
@deprecate_kwarg(old_arg_name='box', new_arg_name=None)
1821
def to_timedelta(arg, unit='ns', box=True, errors='raise'):
1922
"""
2023
Convert argument to timedelta.
@@ -40,6 +43,12 @@ def to_timedelta(arg, unit='ns', box=True, errors='raise'):
4043
- If True returns a Timedelta/TimedeltaIndex of the results.
4144
- If False returns a numpy.timedelta64 or numpy.darray of
4245
values of dtype timedelta64[ns].
46+
47+
.. deprecated:: 0.24.0
48+
Use :meth:`.to_numpy` or :meth:`Timedelta.to_timedelta64`
49+
instead to get an ndarray of values or numpy.timedelta64,
50+
respectively.
51+
4352
errors : {'ignore', 'raise', 'coerce'}, default 'raise'
4453
- If 'raise', then invalid parsing will raise an exception.
4554
- If 'coerce', then invalid parsing will be set as NaT.

pandas/io/parsers.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414

1515
import numpy as np
1616

17+
from pandas import DatetimeIndex
18+
1719
import pandas._libs.lib as lib
1820
import pandas._libs.ops as libops
1921
import pandas._libs.parsers as parsers
20-
from pandas._libs.tslibs import parsing
22+
from pandas._libs.tslibs import parsing, Timestamp
2123
import pandas.compat as compat
2224
from pandas.compat import (
2325
PY3, StringIO, lrange, lzip, map, range, string_types, u, zip)
@@ -3164,11 +3166,11 @@ def converter(*date_cols):
31643166
return tools.to_datetime(
31653167
ensure_object(strs),
31663168
utc=None,
3167-
box=False,
31683169
dayfirst=dayfirst,
31693170
errors='ignore',
31703171
infer_datetime_format=infer_datetime_format
3171-
)
3172+
).to_numpy()
3173+
31723174
except ValueError:
31733175
return tools.to_datetime(
31743176
parsing.try_parse_dates(strs, dayfirst=dayfirst))

pandas/tests/indexes/datetimes/test_tools.py

+40-20
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,13 @@ def test_to_datetime_format_weeks(self, cache):
221221
def test_to_datetime_parse_tzname_or_tzoffset(self, box, const,
222222
fmt, dates, expected_dates):
223223
# GH 13486
224-
result = pd.to_datetime(dates, format=fmt, box=box)
225-
expected = const(expected_dates)
226-
tm.assert_equal(result, expected)
224+
with tm.assert_produces_warning(FutureWarning):
225+
result = pd.to_datetime(dates, format=fmt, box=box)
226+
expected = const(expected_dates)
227+
tm.assert_equal(result, expected)
227228

228-
with pytest.raises(ValueError):
229-
pd.to_datetime(dates, format=fmt, box=box, utc=True)
229+
with pytest.raises(ValueError):
230+
pd.to_datetime(dates, format=fmt, box=box, utc=True)
230231

231232
@pytest.mark.parametrize('offset', [
232233
'+0', '-1foo', 'UTCbar', ':10', '+01:000:01', ''])
@@ -256,7 +257,7 @@ def test_to_datetime_dtarr(self, tz):
256257
result = to_datetime(arr)
257258
assert result is arr
258259

259-
result = to_datetime(arr, box=True)
260+
result = to_datetime(arr)
260261
assert result is arr
261262

262263
def test_to_datetime_pydatetime(self):
@@ -364,7 +365,7 @@ def test_to_datetime_array_of_dt64s(self, cache):
364365
# Assuming all datetimes are in bounds, to_datetime() returns
365366
# an array that is equal to Timestamp() parsing
366367
tm.assert_numpy_array_equal(
367-
pd.to_datetime(dts, box=False, cache=cache),
368+
pd.to_datetime(dts, cache=cache).to_numpy(),
368369
np.array([Timestamp(x).asm8 for x in dts])
369370
)
370371

@@ -376,8 +377,8 @@ def test_to_datetime_array_of_dt64s(self, cache):
376377
pd.to_datetime(dts_with_oob, errors='raise')
377378

378379
tm.assert_numpy_array_equal(
379-
pd.to_datetime(dts_with_oob, box=False, errors='coerce',
380-
cache=cache),
380+
pd.to_datetime(dts_with_oob, errors='coerce',
381+
cache=cache).to_numpy(),
381382
np.array(
382383
[
383384
Timestamp(dts_with_oob[0]).asm8,
@@ -392,8 +393,8 @@ def test_to_datetime_array_of_dt64s(self, cache):
392393
# are converted to their .item(), which depending on the version of
393394
# numpy is either a python datetime.datetime or datetime.date
394395
tm.assert_numpy_array_equal(
395-
pd.to_datetime(dts_with_oob, box=False, errors='ignore',
396-
cache=cache),
396+
pd.to_datetime(dts_with_oob, errors='ignore',
397+
cache=cache).to_numpy(),
397398
np.array(
398399
[dt.item() for dt in dts_with_oob],
399400
dtype='O'
@@ -628,10 +629,14 @@ def test_to_datetime_cache(self, utc, format, box, constructor):
628629
date = '20130101 00:00:00'
629630
test_dates = [date] * 10**5
630631
data = constructor(test_dates)
631-
result = pd.to_datetime(data, utc=utc, format=format, box=box,
632-
cache=True)
633-
expected = pd.to_datetime(data, utc=utc, format=format, box=box,
634-
cache=False)
632+
633+
with tm.assert_produces_warning(FutureWarning):
634+
result = pd.to_datetime(data, utc=utc, format=format, box=box,
635+
cache=True)
636+
637+
with tm.assert_produces_warning(FutureWarning):
638+
expected = pd.to_datetime(data, utc=utc, format=format, box=box,
639+
cache=False)
635640
if box:
636641
tm.assert_index_equal(result, expected)
637642
else:
@@ -684,7 +689,10 @@ def test_iso_8601_strings_with_same_offset(self):
684689
def test_iso_8601_strings_same_offset_no_box(self):
685690
# GH 22446
686691
data = ['2018-01-04 09:01:00+09:00', '2018-01-04 09:02:00+09:00']
687-
result = pd.to_datetime(data, box=False)
692+
693+
with tm.assert_produces_warning(FutureWarning):
694+
result = pd.to_datetime(data, box=False)
695+
688696
expected = np.array([
689697
datetime(2018, 1, 4, 9, 1, tzinfo=pytz.FixedOffset(540)),
690698
datetime(2018, 1, 4, 9, 2, tzinfo=pytz.FixedOffset(540))
@@ -753,6 +761,16 @@ def test_timestamp_utc_true(self, ts, expected):
753761
result = to_datetime(ts, utc=True)
754762
assert result == expected
755763

764+
def test_to_datetime_box_deprecated(self):
765+
expected = np.datetime64('2018-09-09')
766+
767+
# Deprecated - see GH24416
768+
with tm.assert_produces_warning(FutureWarning):
769+
pd.to_datetime(expected, box=False)
770+
771+
result = pd.to_datetime(expected).to_datetime64()
772+
assert result == expected
773+
756774

757775
class TestToDatetimeUnit(object):
758776
@pytest.mark.parametrize('cache', [True, False])
@@ -891,7 +909,7 @@ def test_unit_rounding(self, cache):
891909
def test_unit_ignore_keeps_name(self, cache):
892910
# GH 21697
893911
expected = pd.Index([15e9] * 2, name='name')
894-
result = pd.to_datetime(expected, errors='ignore', box=True, unit='s',
912+
result = pd.to_datetime(expected, errors='ignore', unit='s',
895913
cache=cache)
896914
tm.assert_index_equal(result, expected)
897915

@@ -1052,7 +1070,10 @@ def test_dataframe_box_false(self):
10521070
df = pd.DataFrame({'year': [2015, 2016],
10531071
'month': [2, 3],
10541072
'day': [4, 5]})
1055-
result = pd.to_datetime(df, box=False)
1073+
1074+
with tm.assert_produces_warning(FutureWarning):
1075+
result = pd.to_datetime(df, box=False)
1076+
10561077
expected = np.array(['2015-02-04', '2016-03-05'],
10571078
dtype='datetime64[ns]')
10581079
tm.assert_numpy_array_equal(result, expected)
@@ -1069,8 +1090,7 @@ def test_dataframe_utc_true(self):
10691090

10701091
def test_to_datetime_errors_ignore_utc_true(self):
10711092
# GH 23758
1072-
result = pd.to_datetime([1], unit='s', box=True, utc=True,
1073-
errors='ignore')
1093+
result = pd.to_datetime([1], unit='s', utc=True, errors='ignore')
10741094
expected = DatetimeIndex(['1970-01-01 00:00:01'], tz='UTC')
10751095
tm.assert_index_equal(result, expected)
10761096

pandas/tests/indexes/timedeltas/test_tools.py

+54-34
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,18 @@ def conv(v):
1919

2020
d1 = np.timedelta64(1, 'D')
2121

22-
assert (to_timedelta('1 days 06:05:01.00003', box=False) ==
23-
conv(d1 + np.timedelta64(6 * 3600 + 5 * 60 + 1, 's') +
24-
np.timedelta64(30, 'us')))
25-
assert (to_timedelta('15.5us', box=False) ==
26-
conv(np.timedelta64(15500, 'ns')))
22+
with tm.assert_produces_warning(FutureWarning):
23+
assert (to_timedelta('1 days 06:05:01.00003', box=False) ==
24+
conv(d1 + np.timedelta64(6 * 3600 + 5 * 60 + 1, 's') +
25+
np.timedelta64(30, 'us')))
2726

28-
# empty string
29-
result = to_timedelta('', box=False)
30-
assert result.astype('int64') == iNaT
27+
with tm.assert_produces_warning(FutureWarning):
28+
assert (to_timedelta('15.5us', box=False) ==
29+
conv(np.timedelta64(15500, 'ns')))
30+
31+
# empty string
32+
result = to_timedelta('', box=False)
33+
assert result.astype('int64') == iNaT
3134

3235
result = to_timedelta(['', ''])
3336
assert isna(result).all()
@@ -37,10 +40,11 @@ def conv(v):
3740
expected = pd.Index(np.array([np.timedelta64(1, 's')]))
3841
tm.assert_index_equal(result, expected)
3942

40-
# ints
41-
result = np.timedelta64(0, 'ns')
42-
expected = to_timedelta(0, box=False)
43-
assert result == expected
43+
with tm.assert_produces_warning(FutureWarning):
44+
# ints
45+
result = np.timedelta64(0, 'ns')
46+
expected = to_timedelta(0, box=False)
47+
assert result == expected
4448

4549
# Series
4650
expected = Series([timedelta(days=1), timedelta(days=1, seconds=1)])
@@ -53,16 +57,18 @@ def conv(v):
5357
expected = to_timedelta([0, 10], unit='s')
5458
tm.assert_index_equal(result, expected)
5559

56-
# single element conversion
57-
v = timedelta(seconds=1)
58-
result = to_timedelta(v, box=False)
59-
expected = np.timedelta64(timedelta(seconds=1))
60-
assert result == expected
60+
with tm.assert_produces_warning(FutureWarning):
61+
# single element conversion
62+
v = timedelta(seconds=1)
63+
result = to_timedelta(v, box=False)
64+
expected = np.timedelta64(timedelta(seconds=1))
65+
assert result == expected
6166

62-
v = np.timedelta64(timedelta(seconds=1))
63-
result = to_timedelta(v, box=False)
64-
expected = np.timedelta64(timedelta(seconds=1))
65-
assert result == expected
67+
with tm.assert_produces_warning(FutureWarning):
68+
v = np.timedelta64(timedelta(seconds=1))
69+
result = to_timedelta(v, box=False)
70+
expected = np.timedelta64(timedelta(seconds=1))
71+
assert result == expected
6672

6773
# arrays of various dtypes
6874
arr = np.array([1] * 5, dtype='int64')
@@ -90,22 +96,26 @@ def conv(v):
9096
expected = TimedeltaIndex([np.timedelta64(1, 'D')] * 5)
9197
tm.assert_index_equal(result, expected)
9298

93-
# Test with lists as input when box=false
94-
expected = np.array(np.arange(3) * 1000000000, dtype='timedelta64[ns]')
95-
result = to_timedelta(range(3), unit='s', box=False)
96-
tm.assert_numpy_array_equal(expected, result)
99+
with tm.assert_produces_warning(FutureWarning):
100+
# Test with lists as input when box=false
101+
expected = np.array(np.arange(3) * 1000000000, dtype='timedelta64[ns]')
102+
result = to_timedelta(range(3), unit='s', box=False)
103+
tm.assert_numpy_array_equal(expected, result)
97104

98-
result = to_timedelta(np.arange(3), unit='s', box=False)
99-
tm.assert_numpy_array_equal(expected, result)
105+
with tm.assert_produces_warning(FutureWarning):
106+
result = to_timedelta(np.arange(3), unit='s', box=False)
107+
tm.assert_numpy_array_equal(expected, result)
100108

101-
result = to_timedelta([0, 1, 2], unit='s', box=False)
102-
tm.assert_numpy_array_equal(expected, result)
109+
with tm.assert_produces_warning(FutureWarning):
110+
result = to_timedelta([0, 1, 2], unit='s', box=False)
111+
tm.assert_numpy_array_equal(expected, result)
103112

104-
# Tests with fractional seconds as input:
105-
expected = np.array(
106-
[0, 500000000, 800000000, 1200000000], dtype='timedelta64[ns]')
107-
result = to_timedelta([0., 0.5, 0.8, 1.2], unit='s', box=False)
108-
tm.assert_numpy_array_equal(expected, result)
113+
with tm.assert_produces_warning(FutureWarning):
114+
# Tests with fractional seconds as input:
115+
expected = np.array(
116+
[0, 500000000, 800000000, 1200000000], dtype='timedelta64[ns]')
117+
result = to_timedelta([0., 0.5, 0.8, 1.2], unit='s', box=False)
118+
tm.assert_numpy_array_equal(expected, result)
109119

110120
def test_to_timedelta_invalid(self):
111121

@@ -173,3 +183,13 @@ def test_to_timedelta_on_missing_values(self):
173183

174184
actual = pd.to_timedelta(pd.NaT)
175185
assert actual.value == timedelta_NaT.astype('int64')
186+
187+
def test_to_timedelta_box_deprecated(self):
188+
result = np.timedelta64(0, 'ns')
189+
190+
# Deprecated - see GH24416
191+
with tm.assert_produces_warning(FutureWarning):
192+
to_timedelta(0, box=False)
193+
194+
expected = to_timedelta(0).to_timedelta64()
195+
assert result == expected

0 commit comments

Comments
 (0)