-
-
Notifications
You must be signed in to change notification settings - Fork 18.5k
BUG: Fix series.round() handling of EA #26817
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 7 commits
6b88dcb
6c2ca29
0a8ef62
f038c18
068d8ee
5af678a
85993a2
a527131
ffabac2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,8 @@ | |
from pandas.api.extensions import register_extension_dtype | ||
from pandas.core.arrays import ExtensionArray, ExtensionScalarOpsMixin | ||
|
||
_should_cast_results = [np.repeat] | ||
|
||
|
||
@register_extension_dtype | ||
class DecimalDtype(ExtensionDtype): | ||
|
@@ -59,14 +61,28 @@ def __init__(self, values, dtype=None, copy=False, context=None): | |
values = np.asarray(values, dtype=object) | ||
|
||
self._data = values | ||
# Some aliases for common attribute names to ensure pandas supports | ||
# these | ||
self._items = self.data = self._data | ||
# those aliases are currently not working due to assumptions | ||
# in internal code (GH-20735) | ||
# self._values = self.values = self.data | ||
self._dtype = DecimalDtype(context) | ||
|
||
# aliases for common attribute names, to ensure pandas supports these | ||
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 this related to the rounding changes? 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. This issue helped me write a bug while working on the rounding changes, and I fixed it to protect myself. does that count as related? |
||
@property | ||
def _items(self): | ||
return self._data | ||
|
||
@property | ||
def data(self): | ||
return self._data | ||
|
||
# those aliases are currently not working due to assumptions | ||
# in internal code (GH-20735) | ||
# @property | ||
# def _values(self): | ||
# return self._data | ||
|
||
# @property | ||
# def values(self): | ||
# return self._data | ||
# end aliases | ||
|
||
@property | ||
def dtype(self): | ||
return self._dtype | ||
|
@@ -153,6 +169,40 @@ def _reduce(self, name, skipna=True, **kwargs): | |
"the {} operation".format(name)) | ||
return op(axis=0) | ||
|
||
# numpy experimental NEP-18 (opt-in numpy 1.16, enabled in in 1.17) | ||
def __array_function__(self, func, types, args, kwargs): | ||
def coerce_EA(coll): | ||
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. This doesn't seem like a good idea. For now, just use 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. I've already said I'm not thrilled with this approach, but I'm not sure what you're suggesting.
|
||
# In order to delegate to numpy, we have to coerce any | ||
# ExtensionArrays to the best numpy-friendly dtype approximation | ||
# Different functions take different arguments, which may be | ||
# nested collections, so we look at everything. Sigh. | ||
for i in range(len(coll)): | ||
if isinstance(coll[i], (tuple, list)): | ||
coll[i] = coerce_EA(list(coll[i])) | ||
else: | ||
if isinstance(coll[i], DecimalArray): | ||
# TODO: how to check for any ndarray-like with | ||
# non-numpy dtype? | ||
coll[i] = np.array(coll[i], dtype=object) | ||
|
||
return coll | ||
|
||
if func is np.round_: | ||
values = [decimal.Decimal(round(_)) | ||
for _ in self._data] | ||
return DecimalArray(values, dtype=self.dtype) | ||
|
||
elif True: # just assume we can handle all functions | ||
args = coerce_EA(list(args)) | ||
result = func(*args, **kwargs) | ||
|
||
if func in _should_cast_results: | ||
result = pd.array(result, dtype=self.dtype) | ||
|
||
return result | ||
else: | ||
return NotImplemented | ||
|
||
|
||
def to_decimal(values, context=None): | ||
return DecimalArray([decimal.Decimal(x) for x in values], context=context) | ||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test seemed to raise with right error message, but without the quote. I'll revert and see if the CI fails again.