Skip to content
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

DEPR: dropna multiple axes, fillna int for td64, from_codes with floats, Series.nonzero #29875

Merged
merged 8 commits into from
Dec 1, 2019
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