Skip to content

Commit f2d8db1

Browse files
jbrockmendeljreback
authored andcommitted
Tests for TDI issues already fixed (#19044)
1 parent 7663a63 commit f2d8db1

File tree

4 files changed

+87
-15
lines changed

4 files changed

+87
-15
lines changed

doc/source/whatsnew/v0.23.0.txt

+5-1
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,11 @@ Conversion
338338
- Bug in :class:`Series` floor-division where operating on a scalar ``timedelta`` raises an exception (:issue:`18846`)
339339
- Bug in :class:`FY5253Quarter`, :class:`LastWeekOfMonth` where rollback and rollforward behavior was inconsistent with addition and subtraction behavior (:issue:`18854`)
340340
- Bug in :class:`Index` constructor with ``dtype=CategoricalDtype(...)`` where ``categories`` and ``ordered`` are not maintained (issue:`19032`)
341-
341+
- Bug in :class:`Index` constructor with ``dtype=CategoricalDtype(...)`` where ``categories`` and ``ordered`` are not maintained (issue:`19032`)
342+
- Bug in :class:`Series`` with ``dtype='timedelta64[ns]`` where addition or subtraction of ``TimedeltaIndex`` had results cast to ``dtype='int64'`` (:issue:`17250`)
343+
- Bug in :class:`TimedeltaIndex` where division by a ``Series`` would return a ``TimedeltaIndex`` instead of a ``Series`` (issue:`19042`)
344+
- Bug in :class:`Series` with ``dtype='timedelta64[ns]`` where addition or subtraction of ``TimedeltaIndex`` could return a ``Series`` with an incorrect name (issue:`19043`)
345+
-
342346

343347
Indexing
344348
^^^^^^^^

pandas/core/indexes/timedeltas.py

+3
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,9 @@ def _add_delta(self, delta):
371371
return result
372372

373373
def _evaluate_with_timedelta_like(self, other, op, opstr):
374+
if isinstance(other, ABCSeries):
375+
# GH#19042
376+
return NotImplemented
374377

375378
# allow division by a timedelta
376379
if opstr in ['__div__', '__truediv__', '__floordiv__']:

pandas/core/ops.py

+11-14
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,15 @@ def _align_method_SERIES(left, right, align_asobject=False):
597597

598598

599599
def _construct_result(left, result, index, name, dtype):
600-
return left._constructor(result, index=index, name=name, dtype=dtype)
600+
"""
601+
If the raw op result has a non-None name (e.g. it is an Index object) and
602+
the name argument is None, then passing name to the constructor will
603+
not be enough; we still need to override the name attribute.
604+
"""
605+
out = left._constructor(result, index=index, dtype=dtype)
606+
607+
out.name = name
608+
return out
601609

602610

603611
def _construct_divmod_result(left, result, index, name, dtype):
@@ -687,21 +695,10 @@ def wrapper(left, right, name=name, na_op=na_op):
687695
not isinstance(lvalues, ABCDatetimeIndex)):
688696
lvalues = lvalues.values
689697

690-
if isinstance(right, (ABCSeries, pd.Index)):
691-
# `left` is always a Series object
692-
res_name = _maybe_match_name(left, right)
693-
else:
694-
res_name = left.name
695-
696698
result = wrap_results(safe_na_op(lvalues, rvalues))
697699
res_name = _get_series_op_result_name(left, right)
698-
return construct_result(
699-
left,
700-
result,
701-
index=left.index,
702-
name=res_name,
703-
dtype=dtype,
704-
)
700+
return construct_result(left, result,
701+
index=left.index, name=res_name, dtype=dtype)
705702

706703
return wrapper
707704

pandas/tests/series/test_operators.py

+68
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,74 @@ def test_timedelta_floordiv(self, scalar_td):
10451045
expected = Series([0, 0, np.nan])
10461046
tm.assert_series_equal(result, expected)
10471047

1048+
@pytest.mark.parametrize('names', [(None, None, None),
1049+
('Egon', 'Venkman', None),
1050+
('NCC1701D', 'NCC1701D', 'NCC1701D')])
1051+
def test_td64_series_with_tdi(self, names):
1052+
# GH#17250 make sure result dtype is correct
1053+
# GH#19043 make sure names are propogated correctly
1054+
tdi = pd.TimedeltaIndex(['0 days', '1 day'], name=names[0])
1055+
ser = Series([Timedelta(hours=3), Timedelta(hours=4)], name=names[1])
1056+
expected = Series([Timedelta(hours=3), Timedelta(days=1, hours=4)],
1057+
name=names[2])
1058+
1059+
result = tdi + ser
1060+
tm.assert_series_equal(result, expected)
1061+
assert result.dtype == 'timedelta64[ns]'
1062+
1063+
result = ser + tdi
1064+
tm.assert_series_equal(result, expected)
1065+
assert result.dtype == 'timedelta64[ns]'
1066+
1067+
expected = Series([Timedelta(hours=-3), Timedelta(days=1, hours=-4)],
1068+
name=names[2])
1069+
1070+
result = tdi - ser
1071+
tm.assert_series_equal(result, expected)
1072+
assert result.dtype == 'timedelta64[ns]'
1073+
1074+
result = ser - tdi
1075+
tm.assert_series_equal(result, -expected)
1076+
assert result.dtype == 'timedelta64[ns]'
1077+
1078+
@pytest.mark.parametrize('names', [(None, None, None),
1079+
('Egon', 'Venkman', None),
1080+
('NCC1701D', 'NCC1701D', 'NCC1701D')])
1081+
def test_tdi_mul_int_series(self, names):
1082+
# GH#19042
1083+
tdi = pd.TimedeltaIndex(['0days', '1day', '2days', '3days', '4days'],
1084+
name=names[0])
1085+
ser = Series([0, 1, 2, 3, 4], dtype=np.int64, name=names[1])
1086+
1087+
expected = Series(['0days', '1day', '4days', '9days', '16days'],
1088+
dtype='timedelta64[ns]',
1089+
name=names[2])
1090+
1091+
result = ser * tdi
1092+
tm.assert_series_equal(result, expected)
1093+
1094+
# The direct operation tdi * ser still needs to be fixed.
1095+
result = ser.__rmul__(tdi)
1096+
tm.assert_series_equal(result, expected)
1097+
1098+
@pytest.mark.parametrize('names', [(None, None, None),
1099+
('Egon', 'Venkman', None),
1100+
('NCC1701D', 'NCC1701D', 'NCC1701D')])
1101+
def test_float_series_rdiv_tdi(self, names):
1102+
# GH#19042
1103+
# TODO: the direct operation TimedeltaIndex / Series still
1104+
# needs to be fixed.
1105+
tdi = pd.TimedeltaIndex(['0days', '1day', '2days', '3days', '4days'],
1106+
name=names[0])
1107+
ser = Series([1.5, 3, 4.5, 6, 7.5], dtype=np.float64, name=names[1])
1108+
1109+
expected = Series([tdi[n] / ser[n] for n in range(len(ser))],
1110+
dtype='timedelta64[ns]',
1111+
name=names[2])
1112+
1113+
result = ser.__rdiv__(tdi)
1114+
tm.assert_series_equal(result, expected)
1115+
10481116

10491117
class TestDatetimeSeriesArithmetic(object):
10501118
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)