Skip to content

DEPR: enforce Sparse deprecations #58167

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 1 commit into from
Apr 5, 2024
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
2 changes: 2 additions & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ Removal of prior version deprecations/changes
- All arguments except ``name`` in :meth:`Index.rename` are now keyword only (:issue:`56493`)
- All arguments except the first ``path``-like argument in IO writers are now keyword only (:issue:`54229`)
- Disallow calling :meth:`Series.replace` or :meth:`DataFrame.replace` without a ``value`` and with non-dict-like ``to_replace`` (:issue:`33302`)
- Disallow constructing a :class:`arrays.SparseArray` with scalar data (:issue:`53039`)
- Disallow non-standard (``np.ndarray``, :class:`Index`, :class:`ExtensionArray`, or :class:`Series`) to :func:`isin`, :func:`unique`, :func:`factorize` (:issue:`52986`)
- Disallow passing a pandas type to :meth:`Index.view` (:issue:`55709`)
- Disallow units other than "s", "ms", "us", "ns" for datetime64 and timedelta64 dtypes in :func:`array` (:issue:`53817`)
Expand All @@ -216,6 +217,7 @@ Removal of prior version deprecations/changes
- Removed deprecated "method" and "limit" keywords from :meth:`Series.replace` and :meth:`DataFrame.replace` (:issue:`53492`)
- Removed extension test classes ``BaseNoReduceTests``, ``BaseNumericReduceTests``, ``BaseBooleanReduceTests`` (:issue:`54663`)
- Removed the "closed" and "normalize" keywords in :meth:`DatetimeIndex.__new__` (:issue:`52628`)
- Require :meth:`SparseDtype.fill_value` to be a valid value for the :meth:`SparseDtype.subtype` (:issue:`53043`)
- Stopped performing dtype inference with in :meth:`Index.insert` with object-dtype index; this often affects the index/columns that result when setting new entries into an empty :class:`Series` or :class:`DataFrame` (:issue:`51363`)
- Removed the "closed" and "unit" keywords in :meth:`TimedeltaIndex.__new__` (:issue:`52628`, :issue:`55499`)
- All arguments in :meth:`Index.sort_values` are now keyword only (:issue:`56493`)
Expand Down
16 changes: 3 additions & 13 deletions pandas/core/arrays/sparse/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@

from pandas.core.dtypes.astype import astype_array
from pandas.core.dtypes.cast import (
construct_1d_arraylike_from_scalar,
find_common_type,
maybe_box_datetimelike,
)
Expand Down Expand Up @@ -399,19 +398,10 @@ def __init__(
dtype = dtype.subtype

if is_scalar(data):
warnings.warn(
f"Constructing {type(self).__name__} with scalar data is deprecated "
"and will raise in a future version. Pass a sequence instead.",
FutureWarning,
stacklevel=find_stack_level(),
raise TypeError(
f"Cannot construct {type(self).__name__} from scalar data. "
"Pass a sequence instead."
)
if sparse_index is None:
npoints = 1
else:
npoints = sparse_index.length

data = construct_1d_arraylike_from_scalar(data, npoints, dtype=None)
dtype = data.dtype

if dtype is not None:
dtype = pandas_dtype(dtype)
Expand Down
18 changes: 6 additions & 12 deletions pandas/core/dtypes/dtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1762,24 +1762,18 @@ def _check_fill_value(self) -> None:
val = self._fill_value
if isna(val):
if not is_valid_na_for_dtype(val, self.subtype):
warnings.warn(
"Allowing arbitrary scalar fill_value in SparseDtype is "
"deprecated. In a future version, the fill_value must be "
"a valid value for the SparseDtype.subtype.",
FutureWarning,
stacklevel=find_stack_level(),
raise ValueError(
# GH#53043
"fill_value must be a valid value for the SparseDtype.subtype"
)
else:
dummy = np.empty(0, dtype=self.subtype)
dummy = ensure_wrapped_if_datetimelike(dummy)

if not can_hold_element(dummy, val):
warnings.warn(
"Allowing arbitrary scalar fill_value in SparseDtype is "
"deprecated. In a future version, the fill_value must be "
"a valid value for the SparseDtype.subtype.",
FutureWarning,
stacklevel=find_stack_level(),
raise ValueError(
# GH#53043
"fill_value must be a valid value for the SparseDtype.subtype"
)

@property
Expand Down
10 changes: 6 additions & 4 deletions pandas/tests/arrays/sparse/test_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ def test_set_fill_value(self):
arr.fill_value = 2
assert arr.fill_value == 2

msg = "Allowing arbitrary scalar fill_value in SparseDtype is deprecated"
with tm.assert_produces_warning(FutureWarning, match=msg):
msg = "fill_value must be a valid value for the SparseDtype.subtype"
with pytest.raises(ValueError, match=msg):
# GH#53043
arr.fill_value = 3.1
assert arr.fill_value == 3.1
assert arr.fill_value == 2

arr.fill_value = np.nan
assert np.isnan(arr.fill_value)
Expand All @@ -64,8 +65,9 @@ def test_set_fill_value(self):
arr.fill_value = True
assert arr.fill_value is True

with tm.assert_produces_warning(FutureWarning, match=msg):
with pytest.raises(ValueError, match=msg):
arr.fill_value = 0
assert arr.fill_value is True

arr.fill_value = np.nan
assert np.isnan(arr.fill_value)
Expand Down
18 changes: 5 additions & 13 deletions pandas/tests/arrays/sparse/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,20 +144,12 @@ def test_constructor_spindex_dtype(self):
@pytest.mark.parametrize("sparse_index", [None, IntIndex(1, [0])])
def test_constructor_spindex_dtype_scalar(self, sparse_index):
# scalar input
msg = "Constructing SparseArray with scalar data is deprecated"
with tm.assert_produces_warning(FutureWarning, match=msg):
arr = SparseArray(data=1, sparse_index=sparse_index, dtype=None)
exp = SparseArray([1], dtype=None)
tm.assert_sp_array_equal(arr, exp)
assert arr.dtype == SparseDtype(np.int64)
assert arr.fill_value == 0
msg = "Cannot construct SparseArray from scalar data. Pass a sequence instead"
with pytest.raises(TypeError, match=msg):
SparseArray(data=1, sparse_index=sparse_index, dtype=None)

with tm.assert_produces_warning(FutureWarning, match=msg):
arr = SparseArray(data=1, sparse_index=IntIndex(1, [0]), dtype=None)
exp = SparseArray([1], dtype=None)
tm.assert_sp_array_equal(arr, exp)
assert arr.dtype == SparseDtype(np.int64)
assert arr.fill_value == 0
with pytest.raises(TypeError, match=msg):
SparseArray(data=1, sparse_index=IntIndex(1, [0]), dtype=None)

def test_constructor_spindex_dtype_scalar_broadcasts(self):
arr = SparseArray(
Expand Down
1 change: 0 additions & 1 deletion pandas/tests/arrays/sparse/test_dtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ def test_nans_not_equal():
(SparseDtype("float64"), SparseDtype("float32")),
(SparseDtype("float64"), SparseDtype("float64", 0)),
(SparseDtype("float64"), SparseDtype("datetime64[ns]", np.nan)),
(SparseDtype(int, pd.NaT), SparseDtype(float, pd.NaT)),
(SparseDtype("float64"), np.dtype("float64")),
]

Expand Down