Skip to content

Commit e3009cb

Browse files
rhshadrachpmhatre1
authored andcommitted
DEPR: Enforce deprecation of previous implementation of DataFrame.stack (pandas-dev#57302)
* DEPR: Enforce deprecation of previous implementation of DataFrame.stack * fixup * whatsnew
1 parent b0b8a97 commit e3009cb

File tree

24 files changed

+86
-77
lines changed

24 files changed

+86
-77
lines changed

doc/source/getting_started/comparison/comparison_with_r.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ In Python, the :meth:`~pandas.melt` method is the R equivalent:
438438
)
439439
440440
pd.melt(cheese, id_vars=["first", "last"])
441-
cheese.set_index(["first", "last"]).stack(future_stack=True) # alternative way
441+
cheese.set_index(["first", "last"]).stack() # alternative way
442442
443443
For more details and examples see :ref:`the reshaping documentation
444444
<reshaping.melt>`.

doc/source/user_guide/10min.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ columns:
563563

564564
.. ipython:: python
565565
566-
stacked = df2.stack(future_stack=True)
566+
stacked = df2.stack()
567567
stacked
568568
569569
With a "stacked" DataFrame or Series (having a :class:`MultiIndex` as the

doc/source/user_guide/cookbook.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ The :ref:`multindexing <advanced.hierarchical>` docs.
311311
df.columns = pd.MultiIndex.from_tuples([tuple(c.split("_")) for c in df.columns])
312312
df
313313
# Now stack & Reset
314-
df = df.stack(0, future_stack=True).reset_index(1)
314+
df = df.stack(0).reset_index(1)
315315
df
316316
# And fix the labels (Notice the label 'level_1' got added automatically)
317317
df.columns = ["Sample", "All_X", "All_Y"]
@@ -688,7 +688,7 @@ The :ref:`Pivot <reshaping.pivot>` docs.
688688
aggfunc="sum",
689689
margins=True,
690690
)
691-
table.stack("City", future_stack=True)
691+
table.stack("City")
692692
693693
`Frequency table like plyr in R
694694
<https://stackoverflow.com/questions/15589354/frequency-tables-in-pandas-like-plyr-in-r>`__

doc/source/user_guide/groupby.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -1721,4 +1721,4 @@ column index name will be used as the name of the inserted column:
17211721
17221722
result
17231723
1724-
result.stack(future_stack=True)
1724+
result.stack()

doc/source/user_guide/reshaping.rst

+6-6
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ as having a multi-level index:
163163

164164
.. ipython:: python
165165
166-
table.stack(future_stack=True)
166+
table.stack()
167167
168168
.. _reshaping.stacking:
169169

@@ -209,7 +209,7 @@ stacked level becomes the new lowest level in a :class:`MultiIndex` on the colum
209209

210210
.. ipython:: python
211211
212-
stacked = df2.stack(future_stack=True)
212+
stacked = df2.stack()
213213
stacked
214214
215215
With a "stacked" :class:`DataFrame` or :class:`Series` (having a :class:`MultiIndex` as the
@@ -245,7 +245,7 @@ will result in a **sorted** copy of the original :class:`DataFrame` or :class:`S
245245
index = pd.MultiIndex.from_product([[2, 1], ["a", "b"]])
246246
df = pd.DataFrame(np.random.randn(4), index=index, columns=["A"])
247247
df
248-
all(df.unstack().stack(future_stack=True) == df.sort_index())
248+
all(df.unstack().stack() == df.sort_index())
249249
250250
.. _reshaping.stack_multiple:
251251

@@ -270,16 +270,16 @@ processed individually.
270270
df = pd.DataFrame(np.random.randn(4, 4), columns=columns)
271271
df
272272
273-
df.stack(level=["animal", "hair_length"], future_stack=True)
273+
df.stack(level=["animal", "hair_length"])
274274
275275
The list of levels can contain either level names or level numbers but
276276
not a mixture of the two.
277277

278278
.. ipython:: python
279279
280-
# df.stack(level=['animal', 'hair_length'], future_stack=True)
280+
# df.stack(level=['animal', 'hair_length'])
281281
# from above is equivalent to:
282-
df.stack(level=[1, 2], future_stack=True)
282+
df.stack(level=[1, 2])
283283
284284
Missing data
285285
~~~~~~~~~~~~

doc/source/whatsnew/v3.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ Removal of prior version deprecations/changes
112112
- All arguments in :meth:`Series.to_dict` are now keyword only (:issue:`56493`)
113113
- Changed the default value of ``observed`` in :meth:`DataFrame.groupby` and :meth:`Series.groupby` to ``True`` (:issue:`51811`)
114114
- Enforced silent-downcasting deprecation for :ref:`all relevant methods <whatsnew_220.silent_downcasting>` (:issue:`54710`)
115+
- In :meth:`DataFrame.stack`, the default value of ``future_stack`` is now ``True``; specifying ``False`` will raise a ``FutureWarning`` (:issue:`55448`)
115116
- Removed ``DataFrame.applymap``, ``Styler.applymap`` and ``Styler.applymap_index`` (:issue:`52364`)
116117
- Removed ``DataFrame.bool`` and ``Series.bool`` (:issue:`51756`)
117118
- Removed ``DataFrame.first`` and ``DataFrame.last`` (:issue:`53710`)

pandas/core/frame.py

+16-21
Original file line numberDiff line numberDiff line change
@@ -9188,7 +9188,7 @@ def stack(
91889188
level: IndexLabel = -1,
91899189
dropna: bool | lib.NoDefault = lib.no_default,
91909190
sort: bool | lib.NoDefault = lib.no_default,
9191-
future_stack: bool = False,
9191+
future_stack: bool = True,
91929192
):
91939193
"""
91949194
Stack the prescribed level(s) from columns to index.
@@ -9261,7 +9261,7 @@ def stack(
92619261
weight height
92629262
cat 0 1
92639263
dog 2 3
9264-
>>> df_single_level_cols.stack(future_stack=True)
9264+
>>> df_single_level_cols.stack()
92659265
cat weight 0
92669266
height 1
92679267
dog weight 2
@@ -9284,7 +9284,7 @@ def stack(
92849284
kg pounds
92859285
cat 1 2
92869286
dog 2 4
9287-
>>> df_multi_level_cols1.stack(future_stack=True)
9287+
>>> df_multi_level_cols1.stack()
92889288
weight
92899289
cat kg 1
92909290
pounds 2
@@ -9308,7 +9308,7 @@ def stack(
93089308
kg m
93099309
cat 1.0 2.0
93109310
dog 3.0 4.0
9311-
>>> df_multi_level_cols2.stack(future_stack=True)
9311+
>>> df_multi_level_cols2.stack()
93129312
weight height
93139313
cat kg 1.0 NaN
93149314
m NaN 2.0
@@ -9319,13 +9319,13 @@ def stack(
93199319
93209320
The first parameter controls which level or levels are stacked:
93219321
9322-
>>> df_multi_level_cols2.stack(0, future_stack=True)
9322+
>>> df_multi_level_cols2.stack(0)
93239323
kg m
93249324
cat weight 1.0 NaN
93259325
height NaN 2.0
93269326
dog weight 3.0 NaN
93279327
height NaN 4.0
9328-
>>> df_multi_level_cols2.stack([0, 1], future_stack=True)
9328+
>>> df_multi_level_cols2.stack([0, 1])
93299329
cat weight kg 1.0
93309330
height m 2.0
93319331
dog weight kg 3.0
@@ -9338,19 +9338,14 @@ def stack(
93389338
stack_multiple,
93399339
)
93409340

9341-
if (
9342-
dropna is not lib.no_default
9343-
or sort is not lib.no_default
9344-
or self.columns.nlevels > 1
9345-
):
9346-
warnings.warn(
9347-
"The previous implementation of stack is deprecated and will be "
9348-
"removed in a future version of pandas. See the What's New notes "
9349-
"for pandas 2.1.0 for details. Specify future_stack=True to adopt "
9350-
"the new implementation and silence this warning.",
9351-
FutureWarning,
9352-
stacklevel=find_stack_level(),
9353-
)
9341+
warnings.warn(
9342+
"The previous implementation of stack is deprecated and will be "
9343+
"removed in a future version of pandas. See the What's New notes "
9344+
"for pandas 2.1.0 for details. Do not specify the future_stack "
9345+
"argument to adopt the new implementation and silence this warning.",
9346+
FutureWarning,
9347+
stacklevel=find_stack_level(),
9348+
)
93549349

93559350
if dropna is lib.no_default:
93569351
dropna = True
@@ -9366,14 +9361,14 @@ def stack(
93669361

93679362
if dropna is not lib.no_default:
93689363
raise ValueError(
9369-
"dropna must be unspecified with future_stack=True as the new "
9364+
"dropna must be unspecified as the new "
93709365
"implementation does not introduce rows of NA values. This "
93719366
"argument will be removed in a future version of pandas."
93729367
)
93739368

93749369
if sort is not lib.no_default:
93759370
raise ValueError(
9376-
"Cannot specify sort with future_stack=True, this argument will be "
9371+
"Cannot specify sort, this argument will be "
93779372
"removed in a future version of pandas. Sort the result using "
93789373
".sort_index instead."
93799374
)

pandas/core/groupby/generic.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ def _wrap_applied_output(
513513
res_df = self.obj._constructor_expanddim(values, index=index)
514514
# if self.observed is False,
515515
# keep all-NaN rows created while re-indexing
516-
res_ser = res_df.stack(future_stack=True)
516+
res_ser = res_df.stack()
517517
res_ser.name = self.obj.name
518518
return res_ser
519519
elif isinstance(values[0], (Series, DataFrame)):

pandas/core/resample.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1370,7 +1370,7 @@ def size(self):
13701370
# If the result is a non-empty DataFrame we stack to get a Series
13711371
# GH 46826
13721372
if isinstance(result, ABCDataFrame) and not result.empty:
1373-
result = result.stack(future_stack=True)
1373+
result = result.stack()
13741374

13751375
if not len(self.ax):
13761376
from pandas import Series

pandas/core/reshape/pivot.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ def _all_key(key):
420420

421421
if len(cols) > 0:
422422
row_margin = data[cols + values].groupby(cols, observed=observed).agg(aggfunc)
423-
row_margin = row_margin.stack(future_stack=True)
423+
row_margin = row_margin.stack()
424424

425425
# GH#26568. Use names instead of indices in case of numeric names
426426
new_order_indices = [len(cols)] + list(range(len(cols)))

pandas/core/reshape/reshape.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ def unstack(
518518
if isinstance(obj.index, MultiIndex):
519519
return _unstack_frame(obj, level, fill_value=fill_value, sort=sort)
520520
else:
521-
return obj.T.stack(future_stack=True)
521+
return obj.T.stack()
522522
elif not isinstance(obj.index, MultiIndex):
523523
# GH 36113
524524
# Give nicer error messages when unstack a Series whose

pandas/tests/extension/json/test_json.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def test_series_constructor_scalar_with_index(self, data, dtype):
127127
@pytest.mark.xfail(reason="Different definitions of NA")
128128
def test_stack(self):
129129
"""
130-
The test does .astype(object).stack(future_stack=True). If we happen to have
130+
The test does .astype(object).stack(). If we happen to have
131131
any missing values in `data`, then we'll end up with different
132132
rows since we consider `{}` NA, but `.astype(object)` doesn't.
133133
"""

pandas/tests/frame/methods/test_reset_index.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def test_reset_index_with_intervals(self):
106106
tm.assert_frame_equal(result2, original)
107107

108108
def test_reset_index(self, float_frame):
109-
stacked = float_frame.stack(future_stack=True)[::2]
109+
stacked = float_frame.stack()[::2]
110110
stacked = DataFrame({"foo": stacked, "bar": stacked})
111111

112112
names = ["first", "second"]
@@ -739,7 +739,7 @@ def test_reset_index_rename(float_frame):
739739

740740
def test_reset_index_rename_multiindex(float_frame):
741741
# GH 6878
742-
stacked_df = float_frame.stack(future_stack=True)[::2]
742+
stacked_df = float_frame.stack()[::2]
743743
stacked_df = DataFrame({"foo": stacked_df, "bar": stacked_df})
744744

745745
names = ["first", "second"]
@@ -753,7 +753,7 @@ def test_reset_index_rename_multiindex(float_frame):
753753

754754
def test_errorreset_index_rename(float_frame):
755755
# GH 6878
756-
stacked_df = float_frame.stack(future_stack=True)[::2]
756+
stacked_df = float_frame.stack()[::2]
757757
stacked_df = DataFrame({"first": stacked_df, "second": stacked_df})
758758

759759
with pytest.raises(

pandas/tests/frame/test_stack_unstack.py

+24-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ def future_stack(request):
2828

2929

3030
class TestDataFrameReshape:
31+
@pytest.mark.filterwarnings(
32+
"ignore:The previous implementation of stack is deprecated"
33+
)
3134
def test_stack_unstack(self, float_frame, future_stack):
3235
df = float_frame.copy()
3336
df[:] = np.arange(np.prod(df.shape)).reshape(df.shape)
@@ -1157,6 +1160,9 @@ def test_stack_full_multiIndex(self, future_stack):
11571160
expected["B"] = expected["B"].astype(df.dtypes.iloc[0])
11581161
tm.assert_frame_equal(result, expected)
11591162

1163+
@pytest.mark.filterwarnings(
1164+
"ignore:The previous implementation of stack is deprecated"
1165+
)
11601166
@pytest.mark.parametrize("ordered", [False, True])
11611167
def test_stack_preserve_categorical_dtype(self, ordered, future_stack):
11621168
# GH13854
@@ -1201,6 +1207,9 @@ def test_stack_multi_preserve_categorical_dtype(
12011207

12021208
tm.assert_series_equal(result, expected)
12031209

1210+
@pytest.mark.filterwarnings(
1211+
"ignore:The previous implementation of stack is deprecated"
1212+
)
12041213
def test_stack_preserve_categorical_dtype_values(self, future_stack):
12051214
# GH-23077
12061215
cat = pd.Categorical(["a", "a", "b", "c"])
@@ -1393,6 +1402,7 @@ def test_unstack_timezone_aware_values():
13931402
tm.assert_frame_equal(result, expected)
13941403

13951404

1405+
@pytest.mark.filterwarnings("ignore:The previous implementation of stack is deprecated")
13961406
def test_stack_timezone_aware_values(future_stack):
13971407
# GH 19420
13981408
ts = date_range(freq="D", start="20180101", end="20180103", tz="America/New_York")
@@ -1719,6 +1729,9 @@ def test_stack(self, multiindex_year_month_day_dataframe_random_data, future_sta
17191729
expected = ymd.unstack(0).stack(0, future_stack=future_stack)
17201730
tm.assert_equal(result, expected)
17211731

1732+
@pytest.mark.filterwarnings(
1733+
"ignore:The previous implementation of stack is deprecated"
1734+
)
17221735
@pytest.mark.parametrize(
17231736
"idx, exp_idx",
17241737
[
@@ -1805,6 +1818,9 @@ def test_stack_mixed_dtype(self, multiindex_dataframe_random_data, future_stack)
18051818
assert result.name is None
18061819
assert stacked["bar"].dtype == np.float64
18071820

1821+
@pytest.mark.filterwarnings(
1822+
"ignore:The previous implementation of stack is deprecated"
1823+
)
18081824
def test_unstack_bug(self, future_stack):
18091825
df = DataFrame(
18101826
{
@@ -1839,6 +1855,9 @@ def test_stack_unstack_preserve_names(
18391855
restacked = unstacked.stack(future_stack=future_stack)
18401856
assert restacked.index.names == frame.index.names
18411857

1858+
@pytest.mark.filterwarnings(
1859+
"ignore:The previous implementation of stack is deprecated"
1860+
)
18421861
@pytest.mark.parametrize("method", ["stack", "unstack"])
18431862
def test_stack_unstack_wrong_level_name(
18441863
self, method, multiindex_dataframe_random_data, future_stack
@@ -2308,6 +2327,9 @@ def test_unstack_preserve_types(
23082327
)
23092328
assert unstacked["F", 1].dtype == np.float64
23102329

2330+
@pytest.mark.filterwarnings(
2331+
"ignore:The previous implementation of stack is deprecated"
2332+
)
23112333
def test_unstack_group_index_overflow(self, future_stack):
23122334
codes = np.tile(np.arange(500), 2)
23132335
level = np.arange(500)
@@ -2610,6 +2632,7 @@ def test_unstack_mixed_level_names(self):
26102632
tm.assert_frame_equal(result, expected)
26112633

26122634

2635+
@pytest.mark.filterwarnings("ignore:The previous implementation of stack is deprecated")
26132636
def test_stack_tuple_columns(future_stack):
26142637
# GH#54948 - test stack when the input has a non-MultiIndex with tuples
26152638
df = DataFrame(
@@ -2643,7 +2666,7 @@ def test_stack_preserves_na(dtype, na_value, test_multiindex):
26432666
else:
26442667
index = Index([na_value], dtype=dtype)
26452668
df = DataFrame({"a": [1]}, index=index)
2646-
result = df.stack(future_stack=True)
2669+
result = df.stack()
26472670

26482671
if test_multiindex:
26492672
expected_index = MultiIndex.from_arrays(

0 commit comments

Comments
 (0)