From a8fa1de34988725e27d713097cbc2ab4b1aa1c63 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Tue, 7 Jan 2020 16:06:20 -0600 Subject: [PATCH 1/3] API: Store name outside attrs This aligns with xarray and h5py: https://github.com/pandas-dev/pandas/pull/29062#issuecomment-545703586 --- pandas/core/series.py | 7 ++++--- pandas/tests/frame/test_api.py | 8 ++++++++ pandas/tests/series/test_api.py | 7 +++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/pandas/core/series.py b/pandas/core/series.py index b81659920cfe8..c968d06852d42 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -159,7 +159,8 @@ class Series(base.IndexOpsMixin, generic.NDFrame): _typ = "series" - _metadata: List[str] = [] + _name: Hashable + _metadata: List[str] = ["name"] _accessors = {"dt", "cat", "str", "sparse"} _deprecations = ( base.IndexOpsMixin._deprecations @@ -425,13 +426,13 @@ def dtypes(self): @property def name(self) -> Optional[Hashable]: - return self.attrs.get("name", None) + return self._name @name.setter def name(self, value: Optional[Hashable]) -> None: if not is_hashable(value): raise TypeError("Series.name must be a hashable type") - self.attrs["name"] = value + object.__setattr__(self, "_name", value) @property def values(self): diff --git a/pandas/tests/frame/test_api.py b/pandas/tests/frame/test_api.py index 26d6a917fe1ca..9263409f7a7f8 100644 --- a/pandas/tests/frame/test_api.py +++ b/pandas/tests/frame/test_api.py @@ -551,3 +551,11 @@ async def test_tab_complete_warning(self, ip): with tm.assert_produces_warning(None): with provisionalcompleter("ignore"): list(ip.Completer.completions("df.", 1)) + + def test_attrs(self): + df = pd.DataFrame({"A": [2, 3]}) + assert df.attrs == {} + df.attrs["version"] = 1 + + result = df.rename(columns=str) + assert result.attrs == {"version": 1} diff --git a/pandas/tests/series/test_api.py b/pandas/tests/series/test_api.py index d235e51d00793..f96d6ddfc357e 100644 --- a/pandas/tests/series/test_api.py +++ b/pandas/tests/series/test_api.py @@ -512,6 +512,13 @@ def test_integer_series_size(self): s = Series(range(9), dtype="Int64") assert s.size == 9 + def test_attrs(self): + s = pd.Series([0, 1], name="abc") + assert s.attrs == {} + s.attrs["version"] = 1 + result = s + 1 + assert result.attrs == {"version": 1} + class TestCategoricalSeries: @pytest.mark.parametrize( From 45d18790c7bee524b19519f0f2c958e0fc0e67cb Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Wed, 8 Jan 2020 06:19:11 -0600 Subject: [PATCH 2/3] optional, experimental, doc --- doc/source/whatsnew/v1.0.0.rst | 1 + pandas/core/generic.py | 4 ++++ pandas/core/series.py | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst index 8564ef0527125..82077f39f6ef7 100755 --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -228,6 +228,7 @@ Other enhancements - Added new writer for exporting Stata dta files in version 118, ``StataWriter118``. This format supports exporting strings containing Unicode characters (:issue:`23573`) - :meth:`Series.map` now accepts ``collections.abc.Mapping`` subclasses as a mapper (:issue:`29733`) - The ``pandas.datetime`` class is now deprecated. Import from ``datetime`` instead (:issue:`30296`) +- Added an experimental :attr:`~DataFrame.attrs` for storing global metadata about a dataset (:issue:`29062`) - :meth:`Timestamp.fromisocalendar` is now compatible with python 3.8 and above (:issue:`28115`) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 24c794cd710a9..c2c95e09da279 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -231,6 +231,10 @@ def _init_mgr(self, mgr, axes=None, dtype=None, copy=False): def attrs(self) -> Dict[Optional[Hashable], Any]: """ Dictionary of global attributes on this object. + + .. warning:: + + attrs is experimental and may change without warning. """ if self._attrs is None: self._attrs = {} diff --git a/pandas/core/series.py b/pandas/core/series.py index c968d06852d42..446654374f37c 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -159,7 +159,7 @@ class Series(base.IndexOpsMixin, generic.NDFrame): _typ = "series" - _name: Hashable + _name: Optional[Hashable] _metadata: List[str] = ["name"] _accessors = {"dt", "cat", "str", "sparse"} _deprecations = ( From e0e7af952f3a4af9b59a60eef4224f4c44e08e35 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Wed, 8 Jan 2020 07:12:52 -0600 Subject: [PATCH 3/3] doc --- doc/source/reference/frame.rst | 2 ++ doc/source/reference/series.rst | 2 ++ 2 files changed, 4 insertions(+) diff --git a/doc/source/reference/frame.rst b/doc/source/reference/frame.rst index 4c9df35ea8d9d..01aa6c60e3b2f 100644 --- a/doc/source/reference/frame.rst +++ b/doc/source/reference/frame.rst @@ -273,6 +273,8 @@ Metadata :attr:`DataFrame.attrs` is a dictionary for storing global metadata for this DataFrame. +.. warning:: ``DataFrame.attrs`` is considered experimental and may change without warning. + .. autosummary:: :toctree: api/ diff --git a/doc/source/reference/series.rst b/doc/source/reference/series.rst index 0639730e2dcde..4ad6a7b014532 100644 --- a/doc/source/reference/series.rst +++ b/doc/source/reference/series.rst @@ -525,6 +525,8 @@ Metadata :attr:`Series.attrs` is a dictionary for storing global metadata for this Series. +.. warning:: ``Series.attrs`` is considered experimental and may change without warning. + .. autosummary:: :toctree: api/