Skip to content

CLN: simplify try_coerce_args #23288

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

Merged
merged 3 commits into from
Oct 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 17 additions & 33 deletions pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ def fillna(self, value, limit=None, inplace=False, downcast=None):

# fillna, but if we cannot coerce, then try again as an ObjectBlock
try:
values, _, _, _ = self._try_coerce_args(self.values, value)
values, _ = self._try_coerce_args(self.values, value)
blocks = self.putmask(mask, value, inplace=inplace)
blocks = [b.make_block(values=self._try_coerce_result(b.values))
for b in blocks]
Expand Down Expand Up @@ -745,7 +745,7 @@ def _try_coerce_args(self, values, other):
type(other).__name__,
type(self).__name__.lower().replace('Block', '')))

return values, False, other, False
return values, other

def _try_coerce_result(self, result):
""" reverse of try_coerce_args """
Expand Down Expand Up @@ -795,8 +795,8 @@ def replace(self, to_replace, value, inplace=False, filter=None,
# try to replace, if we raise an error, convert to ObjectBlock and
# retry
try:
values, _, to_replace, _ = self._try_coerce_args(self.values,
to_replace)
values, to_replace = self._try_coerce_args(self.values,
to_replace)
mask = missing.mask_missing(values, to_replace)
if filter is not None:
filtered_out = ~self.mgr_locs.isin(filter)
Expand Down Expand Up @@ -853,7 +853,7 @@ def setitem(self, indexer, value):
# coerce if block dtype can store value
values = self.values
try:
values, _, value, _ = self._try_coerce_args(values, value)
values, value = self._try_coerce_args(values, value)
# can keep its own dtype
if hasattr(value, 'dtype') and is_dtype_equal(values.dtype,
value.dtype):
Expand Down Expand Up @@ -985,7 +985,7 @@ def putmask(self, mask, new, align=True, inplace=False, axis=0,
new = self.fill_value

if self._can_hold_element(new):
_, _, new, _ = self._try_coerce_args(new_values, new)
_, new = self._try_coerce_args(new_values, new)

if transpose:
new_values = new_values.T
Expand Down Expand Up @@ -1193,7 +1193,7 @@ def _interpolate_with_fill(self, method='pad', axis=0, inplace=False,
return [self.copy()]

values = self.values if inplace else self.values.copy()
values, _, fill_value, _ = self._try_coerce_args(values, fill_value)
values, fill_value = self._try_coerce_args(values, fill_value)
values = missing.interpolate_2d(values, method=method, axis=axis,
limit=limit, fill_value=fill_value,
dtype=self.dtype)
Expand Down Expand Up @@ -1366,8 +1366,7 @@ def func(cond, values, other):
if cond.ravel().all():
return values

values, values_mask, other, other_mask = self._try_coerce_args(
values, other)
values, other = self._try_coerce_args(values, other)

try:
return self._try_coerce_result(expressions.where(
Expand Down Expand Up @@ -1477,7 +1476,7 @@ def quantile(self, qs, interpolation='linear', axis=0, axes=None):
"""
kw = {'interpolation': interpolation}
values = self.get_values()
values, _, _, _ = self._try_coerce_args(values, values)
values, _ = self._try_coerce_args(values, values)

def _nanpercentile1D(values, mask, q, **kw):
# mask is Union[ExtensionArray, ndarray]
Expand Down Expand Up @@ -1714,7 +1713,7 @@ def putmask(self, mask, new, align=True, inplace=False, axis=0,
# use block's copy logic.
# .values may be an Index which does shallow copy by default
new_values = self.values if inplace else self.copy().values
new_values, _, new, _ = self._try_coerce_args(new_values, new)
new_values, new = self._try_coerce_args(new_values, new)

if isinstance(new, np.ndarray) and len(new) == len(mask):
new = new[mask]
Expand Down Expand Up @@ -2129,35 +2128,28 @@ def _try_coerce_args(self, values, other):

Returns
-------
base-type values, values mask, base-type other, other mask
base-type values, base-type other
"""

values_mask = isna(values)
values = values.view('i8')
other_mask = False

if isinstance(other, bool):
raise TypeError
elif is_null_datelike_scalar(other):
other = tslibs.iNaT
other_mask = True
elif isinstance(other, Timedelta):
other_mask = isna(other)
other = other.value
elif isinstance(other, timedelta):
other = Timedelta(other).value
elif isinstance(other, np.timedelta64):
other_mask = isna(other)
other = Timedelta(other).value
elif hasattr(other, 'dtype') and is_timedelta64_dtype(other):
other_mask = isna(other)
other = other.astype('i8', copy=False).view('i8')
else:
# coercion issues
# let higher levels handle
raise TypeError

return values, values_mask, other, other_mask
return values, other

def _try_coerce_result(self, result):
""" reverse of try_coerce_args / try_operate """
Expand Down Expand Up @@ -2343,7 +2335,7 @@ def _try_coerce_args(self, values, other):
# to store DatetimeTZBlock as object
other = other.astype(object).values

return values, False, other, False
return values, other

def should_store(self, value):
return not (issubclass(value.dtype.type,
Expand Down Expand Up @@ -2682,33 +2674,29 @@ def _try_coerce_args(self, values, other):

Returns
-------
base-type values, values mask, base-type other, other mask
base-type values, base-type other
"""

values_mask = isna(values)
values = values.view('i8')

if isinstance(other, bool):
raise TypeError
elif is_null_datelike_scalar(other):
other = tslibs.iNaT
other_mask = True
elif isinstance(other, (datetime, np.datetime64, date)):
other = self._box_func(other)
if getattr(other, 'tz') is not None:
raise TypeError("cannot coerce a Timestamp with a tz on a "
"naive Block")
other_mask = isna(other)
other = other.asm8.view('i8')
elif hasattr(other, 'dtype') and is_datetime64_dtype(other):
other_mask = isna(other)
other = other.astype('i8', copy=False).view('i8')
else:
# coercion issues
# let higher levels handle
raise TypeError

return values, values_mask, other, other_mask
return values, other

def _try_coerce_result(self, result):
""" reverse of try_coerce_args """
Expand Down Expand Up @@ -2855,9 +2843,8 @@ def _try_coerce_args(self, values, other):

Returns
-------
base-type values, values mask, base-type other, other mask
base-type values, base-type other
"""
values_mask = _block_shape(isna(values), ndim=self.ndim)
# asi8 is a view, needs copy
values = _block_shape(values.asi8, ndim=self.ndim)

Expand All @@ -2869,11 +2856,9 @@ def _try_coerce_args(self, values, other):
elif (is_null_datelike_scalar(other) or
(lib.is_scalar(other) and isna(other))):
other = tslibs.iNaT
other_mask = True
elif isinstance(other, self._holder):
if other.tz != self.values.tz:
raise ValueError("incompatible or non tz-aware value")
other_mask = _block_shape(isna(other), ndim=self.ndim)
other = _block_shape(other.asi8, ndim=self.ndim)
elif isinstance(other, (np.datetime64, datetime, date)):
other = tslibs.Timestamp(other)
Expand All @@ -2882,12 +2867,11 @@ def _try_coerce_args(self, values, other):
# test we can have an equal time zone
if tz is None or str(tz) != str(self.values.tz):
raise ValueError("incompatible or non tz-aware value")
other_mask = isna(other)
other = other.value
else:
raise TypeError

return values, values_mask, other, other_mask
return values, other

def _try_coerce_result(self, result):
""" reverse of try_coerce_args """
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/internals/test_internals.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,14 +300,14 @@ def test_try_coerce_arg(self):
block = create_block('datetime', [0])

# coerce None
none_coerced = block._try_coerce_args(block.values, None)[2]
none_coerced = block._try_coerce_args(block.values, None)[1]
assert pd.Timestamp(none_coerced) is pd.NaT

# coerce different types of date bojects
vals = (np.datetime64('2010-10-10'), datetime(2010, 10, 10),
date(2010, 10, 10))
for val in vals:
coerced = block._try_coerce_args(block.values, val)[2]
coerced = block._try_coerce_args(block.values, val)[1]
assert np.int64 == type(coerced)
assert pd.Timestamp('2010-10-10') == pd.Timestamp(coerced)

Expand Down