-
-
Notifications
You must be signed in to change notification settings - Fork 19.4k
implement truediv, rtruediv directly in TimedeltaArray; tests #23829
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
Changes from 1 commit
6ec1f08
4c2cc59
bd2ee96
3275dd9
79901f5
adea273
da9f743
ba9e490
10bb49b
8f276ae
7d56da9
6097789
2037be8
ffedf35
2fc44aa
cd4ff57
641ad20
e0d696f
7d9e677
dfc7af4
55cad6b
d21ae78
d72bf90
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -165,6 +165,7 @@ def _simple_new(cls, values, freq=None, dtype=_TD_DTYPE): | |
| def __new__(cls, values, freq=None, dtype=_TD_DTYPE): | ||
|
|
||
| freq, freq_infer = dtl.maybe_infer_freq(freq) | ||
| values, inferred_freq = sequence_to_td64ns(values) | ||
|
|
||
| values = np.array(values, copy=False) | ||
| if values.dtype == np.object_: | ||
|
|
@@ -328,7 +329,9 @@ def _evaluate_with_timedelta_like(self, other, op): | |
| __rfloordiv__ = _wrap_tdi_op(ops.rfloordiv) | ||
|
|
||
| def __truediv__(self, other): | ||
| # TODO: should we unbox zero_dim? | ||
| # TODO: Decimals? | ||
| other = lib.item_from_zerodim(other) | ||
|
|
||
| if isinstance(other, (ABCSeries, ABCDataFrame, ABCIndexClass)): | ||
| return NotImplemented | ||
|
|
||
|
|
@@ -352,6 +355,13 @@ def __truediv__(self, other): | |
| freq = self.freq.delta / other | ||
| return type(self)(result, freq=freq) | ||
|
|
||
| if not hasattr(other, "dtype"): | ||
| # e.g. list, tuple | ||
| other = np.array(other) | ||
|
|
||
| if len(other) != len(self): | ||
| raise ValueError("Cannot divide vectors with unequal lengths") | ||
|
|
||
| elif is_timedelta64_dtype(other): | ||
| # let numpy handle it | ||
| return self._data / other | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to ensure
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, but that is another level of redirection, while we know this will happen and can directly do the correct thing here?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, since we exclude Series and Index at the start.
I guess we could replace
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the (hopefully not too distant future), TimedeltaArray will no longer be an Index. In this case we would want to explicitly grab the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And what's the return type here? Does this need to be wrapped in a a
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
float-dtyped ndarray |
||
|
|
@@ -371,6 +381,8 @@ def __truediv__(self, other): | |
| return type(self)(result) | ||
|
|
||
| def __rtruediv__(self, other): | ||
| other = lib.item_from_zerodim(other) | ||
|
|
||
jbrockmendel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if isinstance(other, (ABCSeries, ABCDataFrame, ABCIndexClass)): | ||
| return NotImplemented | ||
|
|
||
|
|
@@ -385,6 +397,18 @@ def __rtruediv__(self, other): | |
| # otherwise, dispatch to Timedelta implementation | ||
| return other / self._data | ||
|
|
||
| elif lib.is_scalar(other): | ||
| raise TypeError("Cannot divide {typ} by {cls}" | ||
| .format(typ=type(other).__name__, | ||
| cls=type(self).__name__)) | ||
|
|
||
| if not hasattr(other, "dtype"): | ||
| # e.g. list, tuple | ||
| other = np.array(other) | ||
|
|
||
| if len(other) != len(self): | ||
| raise ValueError("Cannot divide vectors with unequal lengths") | ||
|
|
||
| elif is_timedelta64_dtype(other): | ||
| # let numpy handle it | ||
| return other / self._data | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1183,8 +1183,8 @@ def test_td64arr_div_tdlike_scalar_with_nat(self, two_hours, | |
|
|
||
| def test_td64arr_div_td64_ndarray(self, box_with_array): | ||
| # GH#22631 | ||
| rng = TimedeltaIndex(['1 days', pd.NaT, '2 days'], name='foo') | ||
| expected = pd.Float64Index([12, np.nan, 24], name='foo') | ||
| rng = TimedeltaIndex(['1 days', pd.NaT, '2 days']) | ||
| expected = pd.Float64Index([12, np.nan, 24]) | ||
gfyoung marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| rng = tm.box_expected(rng, box_with_array) | ||
| expected = tm.box_expected(expected, box_with_array) | ||
|
|
@@ -1194,21 +1194,41 @@ def test_td64arr_div_td64_ndarray(self, box_with_array): | |
| tm.assert_equal(result, expected) | ||
|
|
||
| result = rng / tm.box_expected(other, box_with_array) | ||
| tm.assert_equal(result, expected, check_names=False) | ||
| tm.assert_equal(result, expected) | ||
|
|
||
| result = rng / other.astype(object) | ||
| tm.assert_equal(result, expected) | ||
|
|
||
| result = rng / list(other) | ||
| tm.assert_equal(result, expected) | ||
|
|
||
| # reversed op | ||
| expected = 1 / expected | ||
| result = other / rng | ||
| tm.assert_equal(result, expected) | ||
|
|
||
| result = tm.box_expected(other, box_with_array) / rng | ||
| tm.assert_equal(result, expected, check_names=False) | ||
| tm.assert_equal(result, expected) | ||
|
|
||
| result = other.astype(object) / rng | ||
| tm.assert_equal(result, expected) | ||
|
|
||
| result = list(other) / rng | ||
| tm.assert_equal(result, expected) | ||
|
|
||
| def test_tdarr_div_length_mismatch(self, box_with_array): | ||
| rng = TimedeltaIndex(['1 days', pd.NaT, '2 days']) | ||
| mismatched = [1, 2, 3, 4] | ||
|
|
||
| rng = tm.box_expected(rng, box_with_array) | ||
| for obj in [mismatched, mismatched[:2]]: | ||
| # one shorter, one longer | ||
| for other in [obj, np.array(obj), pd.Index(obj)]: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to parameterize this? Potentially via flags to indicate what transformation to perform on Definitely the outer-loop can be parameterized (just use
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's possible, but I'm trying to push back a little bit against over-parametrization. The pytest setup cost is non-trivial |
||
| with pytest.raises(ValueError): | ||
| rng / other | ||
| with pytest.raises(ValueError): | ||
| other / rng | ||
|
|
||
| # ------------------------------------------------------------------ | ||
| # __floordiv__, __rfloordiv__ | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.