-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Frame ops prelims - de-duplicate, remove unused kwargs #19522
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 6 commits
a8cc5c0
ce3e616
cffcf31
6c0811a
2de0268
92749dc
98fdcef
85d501c
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 |
---|---|---|
|
@@ -3915,8 +3915,7 @@ def reorder_levels(self, order, axis=0): | |
# ---------------------------------------------------------------------- | ||
# Arithmetic / combination related | ||
|
||
def _combine_frame(self, other, func, fill_value=None, level=None, | ||
try_cast=True): | ||
def _combine_frame(self, other, func, fill_value=None, level=None): | ||
this, other = self.align(other, join='outer', level=level, copy=False) | ||
new_index, new_columns = this.index, this.columns | ||
|
||
|
@@ -3968,52 +3967,40 @@ def f(i): | |
|
||
def _combine_series(self, other, func, fill_value=None, axis=None, | ||
level=None, try_cast=True): | ||
if fill_value is not None: | ||
raise NotImplementedError("fill_value {fill} not supported." | ||
.format(fill=fill_value)) | ||
|
||
if axis is not None: | ||
axis = self._get_axis_name(axis) | ||
if axis == 'index': | ||
return self._combine_match_index(other, func, level=level, | ||
fill_value=fill_value, | ||
try_cast=try_cast) | ||
return self._combine_match_index(other, func, level=level) | ||
else: | ||
return self._combine_match_columns(other, func, level=level, | ||
fill_value=fill_value, | ||
try_cast=try_cast) | ||
return self._combine_series_infer(other, func, level=level, | ||
fill_value=fill_value, | ||
try_cast=try_cast) | ||
|
||
def _combine_series_infer(self, other, func, level=None, | ||
fill_value=None, try_cast=True): | ||
if len(other) == 0: | ||
return self * np.nan | ||
else: | ||
if not len(other): | ||
return self * np.nan | ||
|
||
if len(self) == 0: | ||
# Ambiguous case, use _series so works with DataFrame | ||
return self._constructor(data=self._series, index=self.index, | ||
columns=self.columns) | ||
if not len(self): | ||
# Ambiguous case, use _series so works with DataFrame | ||
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. what is this comment? 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. Not totally sure. Possibly a holdover from higher-dim implementation? 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. |
||
return self._constructor(data=self._series, index=self.index, | ||
columns=self.columns) | ||
|
||
return self._combine_match_columns(other, func, level=level, | ||
fill_value=fill_value, | ||
try_cast=try_cast) | ||
# default axis is columns | ||
return self._combine_match_columns(other, func, level=level, | ||
try_cast=try_cast) | ||
|
||
def _combine_match_index(self, other, func, level=None, | ||
fill_value=None, try_cast=True): | ||
def _combine_match_index(self, other, func, level=None): | ||
left, right = self.align(other, join='outer', axis=0, level=level, | ||
copy=False) | ||
if fill_value is not None: | ||
raise NotImplementedError("fill_value %r not supported." % | ||
fill_value) | ||
return self._constructor(func(left.values.T, right.values).T, | ||
index=left.index, columns=self.columns, | ||
copy=False) | ||
|
||
def _combine_match_columns(self, other, func, level=None, | ||
fill_value=None, try_cast=True): | ||
def _combine_match_columns(self, other, func, level=None, try_cast=True): | ||
left, right = self.align(other, join='outer', axis=1, level=level, | ||
copy=False) | ||
if fill_value is not None: | ||
raise NotImplementedError("fill_value %r not supported" % | ||
fill_value) | ||
|
||
new_data = left._data.eval(func=func, other=right, | ||
axes=[left.columns, self.index], | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,6 +80,26 @@ def _try_get_item(x): | |
return x | ||
|
||
|
||
def _make_invalid_op(name): | ||
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. consider moving this function to core/ops (and parameterizing so you can use it for index/series) |
||
""" | ||
Return a binary method that always raises a TypeError. | ||
|
||
Parameters | ||
---------- | ||
name : str | ||
|
||
Returns | ||
------- | ||
invalid_op : function | ||
""" | ||
def invalid_op(self, other=None): | ||
raise TypeError("cannot perform {name} with this index type: " | ||
"{typ}".format(name=name, typ=type(self))) | ||
|
||
invalid_op.__name__ = name | ||
return invalid_op | ||
|
||
|
||
class InvalidIndexError(Exception): | ||
pass | ||
|
||
|
@@ -3916,30 +3936,12 @@ def _evaluate_compare(self, other): | |
@classmethod | ||
def _add_numeric_methods_add_sub_disabled(cls): | ||
""" add in the numeric add/sub methods to disable """ | ||
|
||
def _make_invalid_op(name): | ||
def invalid_op(self, other=None): | ||
raise TypeError("cannot perform {name} with this index type: " | ||
"{typ}".format(name=name, typ=type(self))) | ||
|
||
invalid_op.__name__ = name | ||
return invalid_op | ||
|
||
cls.__add__ = cls.__radd__ = __iadd__ = _make_invalid_op('__add__') # noqa | ||
cls.__sub__ = __isub__ = _make_invalid_op('__sub__') # noqa | ||
|
||
@classmethod | ||
def _add_numeric_methods_disabled(cls): | ||
""" add in numeric methods to disable other than add/sub """ | ||
|
||
def _make_invalid_op(name): | ||
def invalid_op(self, other=None): | ||
raise TypeError("cannot perform {name} with this index type: " | ||
"{typ}".format(name=name, typ=type(self))) | ||
|
||
invalid_op.__name__ = name | ||
return invalid_op | ||
|
||
cls.__pow__ = cls.__rpow__ = _make_invalid_op('__pow__') | ||
cls.__mul__ = cls.__rmul__ = _make_invalid_op('__mul__') | ||
cls.__floordiv__ = cls.__rfloordiv__ = _make_invalid_op('__floordiv__') | ||
|
@@ -4147,15 +4149,6 @@ def logical_func(self, *args, **kwargs): | |
@classmethod | ||
def _add_logical_methods_disabled(cls): | ||
""" add in logical methods to disable """ | ||
|
||
def _make_invalid_op(name): | ||
def invalid_op(self, other=None): | ||
raise TypeError("cannot perform {name} with this index type: " | ||
"{typ}".format(name=name, typ=type(self))) | ||
|
||
invalid_op.__name__ = name | ||
return invalid_op | ||
|
||
cls.all = _make_invalid_op('all') | ||
cls.any = _make_invalid_op('any') | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -451,6 +451,18 @@ def test_arith_flex_frame(self): | |
with tm.assert_raises_regex(NotImplementedError, 'fill_value'): | ||
self.frame.add(self.frame.iloc[0], axis='index', fill_value=3) | ||
|
||
def test_arith_flex_zero_len_raises(self): | ||
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. shouldn't these be in test_arithmetic? 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. Eventually yes. The more important grouping for now is that this belongs with the test above it, which I plan to split/parametrize before moving to test_arithmetic |
||
# GH#19522 passing fill_value to frame flex arith methods should | ||
# raise even in the zero-length special cases | ||
ser = pd.Series([]) | ||
df = pd.DataFrame([[1, 2], [3, 4]]) | ||
|
||
with tm.assert_raises_regex(NotImplementedError, 'fill_value'): | ||
df.add(ser, fill_value='E') | ||
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 should raise ValueError, not NIE. 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. The existing implementation raises NIE outside of these corner cases. For the time being I'm assuming there's a reason for that. |
||
|
||
with tm.assert_raises_regex(NotImplementedError, 'fill_value'): | ||
ser.to_frame().sub(df[0], axis=None, fill_value=3) | ||
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. just create the required frame here rather than using 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. Sure. |
||
|
||
def test_binary_ops_align(self): | ||
|
||
# test aligning binary ops | ||
|
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.
need double backticks on NotImplementedError. can you be slightly more descriptive here.
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.
a user is reading this and would want to know what if anything they need to change.