Skip to content

Commit

Permalink
DEPR: dropna multiple axes, fillna int for td64, from_codes with floa…
Browse files Browse the repository at this point in the history
…ts, Series.nonzero (pandas-dev#29875)
  • Loading branch information
jbrockmendel authored and proost committed Dec 19, 2019
1 parent 24cc9dd commit 28ff696
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 140 deletions.
4 changes: 4 additions & 0 deletions doc/source/whatsnew/v1.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,10 @@ or ``matplotlib.Axes.plot``. See :ref:`plotting.formatters` for more.
- In :func:`concat` the default value for ``sort`` has been changed from ``None`` to ``False`` (:issue:`20613`)
- Removed previously deprecated "raise_conflict" argument from :meth:`DataFrame.update`, use "errors" instead (:issue:`23585`)
- Removed previously deprecated keyword "n" from :meth:`DatetimeIndex.shift`, :meth:`TimedeltaIndex.shift`, :meth:`PeriodIndex.shift`, use "periods" instead (:issue:`22458`)
- Passing an integer to :meth:`Series.fillna` or :meth:`DataFrame.fillna` with ``timedelta64[ns]`` dtype now raises ``TypeError`` (:issue:`24694`)
- Passing multiple axes to :meth:`DataFrame.dropna` is no longer supported (:issue:`20995`)
- Removed previously deprecated :meth:`Series.nonzero`, use `to_numpy().nonzero()` instead (:issue:`24048`)
- Passing floating dtype ``codes`` to :meth:`Categorical.from_codes` is no longer supported, pass ``codes.astype(np.int64)`` instead (:issue:`21775`)
- Removed the previously deprecated :meth:`Series.to_dense`, :meth:`DataFrame.to_dense` (:issue:`26684`)
- Removed the previously deprecated :meth:`Index.dtype_str`, use ``str(index.dtype)`` instead (:issue:`27106`)
- :meth:`Categorical.ravel` returns a :class:`Categorical` instead of a ``ndarray`` (:issue:`27199`)
Expand Down
18 changes: 1 addition & 17 deletions pandas/core/arrays/categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
is_dict_like,
is_dtype_equal,
is_extension_array_dtype,
is_float_dtype,
is_integer_dtype,
is_iterator,
is_list_like,
Expand Down Expand Up @@ -646,22 +645,7 @@ def from_codes(cls, codes, categories=None, ordered=None, dtype=None):

codes = np.asarray(codes) # #21767
if len(codes) and not is_integer_dtype(codes):
msg = "codes need to be array-like integers"
if is_float_dtype(codes):
icodes = codes.astype("i8")
if (icodes == codes).all():
msg = None
codes = icodes
warn(
(
"float codes will be disallowed in the future and "
"raise a ValueError"
),
FutureWarning,
stacklevel=2,
)
if msg:
raise ValueError(msg)
raise ValueError("codes need to be array-like integers")

if len(codes) and (codes.max() >= len(dtype.categories) or codes.min() < -1):
raise ValueError("codes need to be between -1 and len(categories)-1")
Expand Down
60 changes: 26 additions & 34 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -4475,7 +4475,7 @@ def dropna(self, axis=0, how="any", thresh=None, subset=None, inplace=False):
* 0, or 'index' : Drop rows which contain missing values.
* 1, or 'columns' : Drop columns which contain missing value.
.. deprecated:: 0.23.0
.. versionchanged:: 1.0.0
Pass tuple or list to drop on multiple axes.
Only a single axis is allowed.
Expand Down Expand Up @@ -4565,43 +4565,35 @@ def dropna(self, axis=0, how="any", thresh=None, subset=None, inplace=False):
inplace = validate_bool_kwarg(inplace, "inplace")
if isinstance(axis, (tuple, list)):
# GH20987
msg = (
"supplying multiple axes to axis is deprecated and "
"will be removed in a future version."
)
warnings.warn(msg, FutureWarning, stacklevel=2)
raise TypeError("supplying multiple axes to axis is no longer supported.")

result = self
for ax in axis:
result = result.dropna(how=how, thresh=thresh, subset=subset, axis=ax)
axis = self._get_axis_number(axis)
agg_axis = 1 - axis

agg_obj = self
if subset is not None:
ax = self._get_axis(agg_axis)
indices = ax.get_indexer_for(subset)
check = indices == -1
if check.any():
raise KeyError(list(np.compress(check, subset)))
agg_obj = self.take(indices, axis=agg_axis)

count = agg_obj.count(axis=agg_axis)

if thresh is not None:
mask = count >= thresh
elif how == "any":
mask = count == len(agg_obj._get_axis(agg_axis))
elif how == "all":
mask = count > 0
else:
axis = self._get_axis_number(axis)
agg_axis = 1 - axis

agg_obj = self
if subset is not None:
ax = self._get_axis(agg_axis)
indices = ax.get_indexer_for(subset)
check = indices == -1
if check.any():
raise KeyError(list(np.compress(check, subset)))
agg_obj = self.take(indices, axis=agg_axis)

count = agg_obj.count(axis=agg_axis)

if thresh is not None:
mask = count >= thresh
elif how == "any":
mask = count == len(agg_obj._get_axis(agg_axis))
elif how == "all":
mask = count > 0
if how is not None:
raise ValueError("invalid how option: {h}".format(h=how))
else:
if how is not None:
raise ValueError("invalid how option: {h}".format(h=how))
else:
raise TypeError("must specify how or thresh")
raise TypeError("must specify how or thresh")

result = self.loc(axis=axis)[mask]
result = self.loc(axis=axis)[mask]

if inplace:
self._update_inplace(result)
Expand Down
12 changes: 4 additions & 8 deletions pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2444,15 +2444,11 @@ def fillna(self, value, **kwargs):
# interpreted as nanoseconds
if is_integer(value):
# Deprecation GH#24694, GH#19233
warnings.warn(
"Passing integers to fillna is deprecated, will "
"raise a TypeError in a future version. To retain "
"the old behavior, pass pd.Timedelta(seconds=n) "
"instead.",
FutureWarning,
stacklevel=6,
raise TypeError(
"Passing integers to fillna for timedelta64[ns] dtype is no "
"longer supporetd. To obtain the old behavior, pass "
"`pd.Timedelta(seconds=n)` instead."
)
value = Timedelta(value, unit="s")
return super().fillna(value, **kwargs)

def should_store(self, value):
Expand Down
49 changes: 0 additions & 49 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,55 +528,6 @@ def compress(self, condition, *args, **kwargs):
nv.validate_compress(args, kwargs)
return self[condition]

def nonzero(self):
"""
Return the *integer* indices of the elements that are non-zero.
.. deprecated:: 0.24.0
Please use .to_numpy().nonzero() as a replacement.
This method is equivalent to calling `numpy.nonzero` on the
series data. For compatibility with NumPy, the return value is
the same (a tuple with an array of indices for each dimension),
but it will always be a one-item tuple because series only have
one dimension.
Returns
-------
numpy.ndarray
Indices of elements that are non-zero.
See Also
--------
numpy.nonzero
Examples
--------
>>> s = pd.Series([0, 3, 0, 4])
>>> s.nonzero()
(array([1, 3]),)
>>> s.iloc[s.nonzero()[0]]
1 3
3 4
dtype: int64
# same return although index of s is different
>>> s = pd.Series([0, 3, 0, 4], index=['a', 'b', 'c', 'd'])
>>> s.nonzero()
(array([1, 3]),)
>>> s.iloc[s.nonzero()[0]]
b 3
d 4
dtype: int64
"""
msg = (
"Series.nonzero() is deprecated "
"and will be removed in a future version."
"Use Series.to_numpy().nonzero() instead"
)
warnings.warn(msg, FutureWarning, stacklevel=2)
return self._values.nonzero()

def put(self, *args, **kwargs):
"""
Apply the `put` method to its `values` attribute if it has one.
Expand Down
10 changes: 4 additions & 6 deletions pandas/tests/arrays/categorical/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,13 +529,11 @@ def test_from_codes_with_float(self):
# empty codes should not raise for floats
Categorical.from_codes([], dtype.categories)

with tm.assert_produces_warning(FutureWarning):
cat = Categorical.from_codes(codes, dtype.categories)
tm.assert_numpy_array_equal(cat.codes, np.array([1, 2, 0], dtype="i1"))
with pytest.raises(ValueError, match="codes need to be array-like integers"):
Categorical.from_codes(codes, dtype.categories)

with tm.assert_produces_warning(FutureWarning):
cat = Categorical.from_codes(codes, dtype=dtype)
tm.assert_numpy_array_equal(cat.codes, np.array([1, 2, 0], dtype="i1"))
with pytest.raises(ValueError, match="codes need to be array-like integers"):
Categorical.from_codes(codes, dtype=dtype)

codes = [1.1, 2.0, 0] # non-integer
with pytest.raises(ValueError, match="codes need to be array-like integers"):
Expand Down
17 changes: 5 additions & 12 deletions pandas/tests/frame/test_missing.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,23 +165,16 @@ def test_dropna_multiple_axes(self):
[7, np.nan, 8, 9],
]
)
cp = df.copy()

# GH20987
with tm.assert_produces_warning(FutureWarning):
result = df.dropna(how="all", axis=[0, 1])
with tm.assert_produces_warning(FutureWarning):
result2 = df.dropna(how="all", axis=(0, 1))
expected = df.dropna(how="all").dropna(how="all", axis=1)

tm.assert_frame_equal(result, expected)
tm.assert_frame_equal(result2, expected)
tm.assert_frame_equal(df, cp)
with pytest.raises(TypeError, match="supplying multiple axes"):
df.dropna(how="all", axis=[0, 1])
with pytest.raises(TypeError, match="supplying multiple axes"):
df.dropna(how="all", axis=(0, 1))

inp = df.copy()
with tm.assert_produces_warning(FutureWarning):
with pytest.raises(TypeError, match="supplying multiple axes"):
inp.dropna(how="all", axis=(0, 1), inplace=True)
tm.assert_frame_equal(inp, expected)

def test_dropna_tz_aware_datetime(self):
# GH13407
Expand Down
22 changes: 8 additions & 14 deletions pandas/tests/series/test_missing.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
MultiIndex,
NaT,
Series,
Timedelta,
Timestamp,
date_range,
isna,
Expand Down Expand Up @@ -60,8 +61,7 @@ def test_timedelta_fillna(self):
td = s.diff()

# reg fillna
with tm.assert_produces_warning(FutureWarning):
result = td.fillna(0)
result = td.fillna(Timedelta(seconds=0))
expected = Series(
[
timedelta(0),
Expand All @@ -73,8 +73,10 @@ def test_timedelta_fillna(self):
tm.assert_series_equal(result, expected)

# interpreted as seconds, deprecated
with tm.assert_produces_warning(FutureWarning):
result = td.fillna(1)
with pytest.raises(TypeError, match="Passing integers to fillna"):
td.fillna(1)

result = td.fillna(Timedelta(seconds=1))
expected = Series(
[
timedelta(seconds=1),
Expand Down Expand Up @@ -122,16 +124,14 @@ def test_timedelta_fillna(self):
# ffill
td[2] = np.nan
result = td.ffill()
with tm.assert_produces_warning(FutureWarning):
expected = td.fillna(0)
expected = td.fillna(Timedelta(seconds=0))
expected[0] = np.nan
tm.assert_series_equal(result, expected)

# bfill
td[2] = np.nan
result = td.bfill()
with tm.assert_produces_warning(FutureWarning):
expected = td.fillna(0)
expected = td.fillna(Timedelta(seconds=0))
expected[2] = timedelta(days=1, seconds=9 * 3600 + 60 + 1)
tm.assert_series_equal(result, expected)

Expand Down Expand Up @@ -1597,12 +1597,6 @@ def test_series_interpolate_intraday(self):

tm.assert_numpy_array_equal(result.values, exp.values)

def test_nonzero_warning(self):
# GH 24048
ser = pd.Series([1, 0, 3, 4])
with tm.assert_produces_warning(FutureWarning):
ser.nonzero()

@pytest.mark.parametrize(
"ind",
[
Expand Down

0 comments on commit 28ff696

Please sign in to comment.