From e255e56fa086e06127268e409adb82f440326273 Mon Sep 17 00:00:00 2001 From: Matthew Roeschke Date: Sun, 16 Jan 2022 08:17:19 -0800 Subject: [PATCH] DEPR: Series/DataFrame/HDFStore.iteritems() (#45321) --- doc/source/user_guide/scale.rst | 2 ++ doc/source/whatsnew/v1.5.0.rst | 1 + pandas/core/arrays/sparse/accessor.py | 2 +- pandas/core/frame.py | 6 ++++++ pandas/core/generic.py | 17 +++++++---------- pandas/core/series.py | 6 ++++++ pandas/io/pytables.py | 12 +++++++++++- pandas/tests/frame/test_api.py | 5 +++++ pandas/tests/groupby/test_apply.py | 2 +- pandas/tests/io/pytables/test_store.py | 9 +++++++++ pandas/tests/series/test_api.py | 5 +++++ pandas/tests/series/test_iteration.py | 6 +++--- 12 files changed, 57 insertions(+), 16 deletions(-) diff --git a/doc/source/user_guide/scale.rst b/doc/source/user_guide/scale.rst index 71aef4fdd75f6..edeebe2e8678c 100644 --- a/doc/source/user_guide/scale.rst +++ b/doc/source/user_guide/scale.rst @@ -275,6 +275,7 @@ column names and dtypes. That's because Dask hasn't actually read the data yet. Rather than executing immediately, doing operations build up a **task graph**. .. ipython:: python + :okwarning: ddf ddf["name"] @@ -333,6 +334,7 @@ known automatically. In this case, since we created the parquet files manually, we need to supply the divisions manually. .. ipython:: python + :okwarning: N = 12 starts = [f"20{i:>02d}-01-01" for i in range(N)] diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 852d24a3d1c4e..acd0de9769d99 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -95,6 +95,7 @@ Other API changes Deprecations ~~~~~~~~~~~~ - Deprecated the keyword ``line_terminator`` in :meth:`DataFrame.to_csv` and :meth:`Series.to_csv`, use ``lineterminator`` instead; this is for consistency with :func:`read_csv` and the standard library 'csv' module (:issue:`9568`) +- Deprecated :meth:`DataFrame.iteritems`, :meth:`Series.iteritems`, :meth:`HDFStore.iteritems` in favor of :meth:`DataFrame.items`, :meth:`Series.items`, :meth:`HDFStore.items` (:issue:`45321`) - .. --------------------------------------------------------------------------- diff --git a/pandas/core/arrays/sparse/accessor.py b/pandas/core/arrays/sparse/accessor.py index 8e61460e3fe0b..015ca8842ec78 100644 --- a/pandas/core/arrays/sparse/accessor.py +++ b/pandas/core/arrays/sparse/accessor.py @@ -339,7 +339,7 @@ def to_coo(self): dtype = dtype.subtype cols, rows, data = [], [], [] - for col, (_, ser) in enumerate(self._parent.iteritems()): + for col, (_, ser) in enumerate(self._parent.items()): sp_arr = ser.array if sp_arr.fill_value != 0: raise ValueError("fill value must be 0 when converting to COO matrix") diff --git a/pandas/core/frame.py b/pandas/core/frame.py index c31c4eb460209..4968fe69d9d63 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -1276,6 +1276,12 @@ def items(self) -> Iterable[tuple[Hashable, Series]]: @Appender(_shared_docs["items"]) def iteritems(self) -> Iterable[tuple[Hashable, Series]]: + warnings.warn( + "iteritems is deprecated and will be removed in a future version. " + "Use .items instead.", + FutureWarning, + stacklevel=find_stack_level(), + ) yield from self.items() def iterrows(self) -> Iterable[tuple[Hashable, Series]]: diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 609c431ba8580..879c7b5a299de 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -1989,10 +1989,6 @@ def items(self): for h in self._info_axis: yield h, self[h] - @doc(items) - def iteritems(self): - return self.items() - def __len__(self) -> int: """Returns length of info axis""" return len(self._info_axis) @@ -5855,7 +5851,13 @@ def astype( new_type = dtype[self.name] return self.astype(new_type, copy, errors) - for col_name in dtype.keys(): + # GH#44417 cast to Series so we can use .iat below, which will be + # robust in case we + from pandas import Series + + dtype_ser = Series(dtype, dtype=object) + + for col_name in dtype_ser.index: if col_name not in self: raise KeyError( "Only a column name can be used for the " @@ -5863,11 +5865,6 @@ def astype( f"'{col_name}' not found in columns." ) - # GH#44417 cast to Series so we can use .iat below, which will be - # robust in case we - from pandas import Series - - dtype_ser = Series(dtype, dtype=object) dtype_ser = dtype_ser.reindex(self.columns, fill_value=None, copy=False) results = [] diff --git a/pandas/core/series.py b/pandas/core/series.py index 5ba796b5a7c85..59441dd5352ab 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1705,6 +1705,12 @@ def items(self) -> Iterable[tuple[Hashable, Any]]: @Appender(items.__doc__) def iteritems(self) -> Iterable[tuple[Hashable, Any]]: + warnings.warn( + "iteritems is deprecated and will be removed in a future version. " + "Use .items instead.", + FutureWarning, + stacklevel=find_stack_level(), + ) return self.items() # ---------------------------------------------------------------------- diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py index 3ce5cb31a127a..cfcdde40549b9 100644 --- a/pandas/io/pytables.py +++ b/pandas/io/pytables.py @@ -692,7 +692,17 @@ def items(self): for g in self.groups(): yield g._v_pathname, g - iteritems = items + def iteritems(self): + """ + iterate on key->group + """ + warnings.warn( + "iteritems is deprecated and will be removed in a future version. " + "Use .items instead.", + FutureWarning, + stacklevel=find_stack_level(), + ) + yield from self.items() def open(self, mode: str = "a", **kwargs): """ diff --git a/pandas/tests/frame/test_api.py b/pandas/tests/frame/test_api.py index 3adc4ebceaad5..4339233064838 100644 --- a/pandas/tests/frame/test_api.py +++ b/pandas/tests/frame/test_api.py @@ -366,3 +366,8 @@ def test_inspect_getmembers(self): df = DataFrame() with tm.assert_produces_warning(None): inspect.getmembers(df) + + def test_dataframe_iteritems_deprecated(self): + df = DataFrame([1]) + with tm.assert_produces_warning(FutureWarning): + next(df.iteritems()) diff --git a/pandas/tests/groupby/test_apply.py b/pandas/tests/groupby/test_apply.py index 22a4ce327c150..2c2877e59667f 100644 --- a/pandas/tests/groupby/test_apply.py +++ b/pandas/tests/groupby/test_apply.py @@ -843,7 +843,7 @@ def test_apply_series_return_dataframe_groups(): ) def most_common_values(df): - return Series({c: s.value_counts().index[0] for c, s in df.iteritems()}) + return Series({c: s.value_counts().index[0] for c, s in df.items()}) result = tdf.groupby("day").apply(most_common_values)["userId"] expected = Series( diff --git a/pandas/tests/io/pytables/test_store.py b/pandas/tests/io/pytables/test_store.py index cbca8bb64e350..73e10adb0c2c3 100644 --- a/pandas/tests/io/pytables/test_store.py +++ b/pandas/tests/io/pytables/test_store.py @@ -1011,3 +1011,12 @@ def test_to_hdf_with_object_column_names(setup_path): df.to_hdf(path, "df", format="table", data_columns=True) result = read_hdf(path, "df", where=f"index = [{df.index[0]}]") assert len(result) + + +def test_hdfstore_iteritems_deprecated(setup_path): + with ensure_clean_path(setup_path) as path: + df = DataFrame({"a": [1]}) + with HDFStore(path, mode="w") as hdf: + hdf.put("table", df) + with tm.assert_produces_warning(FutureWarning): + next(hdf.iteritems()) diff --git a/pandas/tests/series/test_api.py b/pandas/tests/series/test_api.py index 146663d90f752..7d8817e8dfa34 100644 --- a/pandas/tests/series/test_api.py +++ b/pandas/tests/series/test_api.py @@ -203,3 +203,8 @@ def test_series_datetimelike_attribute_access_invalid(self): msg = "'Series' object has no attribute 'weekday'" with pytest.raises(AttributeError, match=msg): ser.weekday + + def test_series_iteritems_deprecated(self): + ser = Series([1]) + with tm.assert_produces_warning(FutureWarning): + next(ser.iteritems()) diff --git a/pandas/tests/series/test_iteration.py b/pandas/tests/series/test_iteration.py index dc9fe9e3bdd34..d5551575b3617 100644 --- a/pandas/tests/series/test_iteration.py +++ b/pandas/tests/series/test_iteration.py @@ -11,15 +11,15 @@ def test_iter_strings(self, string_series): assert val == string_series[i] def test_iteritems_datetimes(self, datetime_series): - for idx, val in datetime_series.iteritems(): + for idx, val in datetime_series.items(): assert val == datetime_series[idx] def test_iteritems_strings(self, string_series): - for idx, val in string_series.iteritems(): + for idx, val in string_series.items(): assert val == string_series[idx] # assert is lazy (generators don't define reverse, lists do) - assert not hasattr(string_series.iteritems(), "reverse") + assert not hasattr(string_series.items(), "reverse") def test_items_datetimes(self, datetime_series): for idx, val in datetime_series.items():