diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index 2b73a84810045..ffa4f1068f84d 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -886,6 +886,9 @@ Deprecations - The ``convert_datetime64`` parameter in :func:`DataFrame.to_records` has been deprecated and will be removed in a future version. The NumPy bug motivating this parameter has been resolved. The default value for this parameter has also changed from ``True`` to ``None`` (:issue:`18160`). - :func:`Series.rolling().apply() `, :func:`DataFrame.rolling().apply() `, :func:`Series.expanding().apply() `, and :func:`DataFrame.expanding().apply() ` have deprecated passing an ``np.array`` by default. One will need to pass the new ``raw`` parameter to be explicit about what is passed (:issue:`20584`) +- The ``data``, ``base``, ``strides``, ``flags`` and ``itemsize`` properties + of the ``Series`` and ``Index`` classes have been deprecated and will be + removed in a future version (:issue:`20419`). - ``DatetimeIndex.offset`` is deprecated. Use ``DatetimeIndex.freq`` instead (:issue:`20716`) - ``Index.get_duplicates()`` is deprecated and will be removed in a future version (:issue:`20239`) diff --git a/pandas/core/algorithms.py b/pandas/core/algorithms.py index 5493348334223..cbc412d74d51d 100644 --- a/pandas/core/algorithms.py +++ b/pandas/core/algorithms.py @@ -1498,6 +1498,8 @@ def take_nd(arr, indexer, axis=0, out=None, fill_value=np.nan, mask_info=None, if is_sparse(arr): arr = arr.get_values() + arr = np.asarray(arr) + if indexer is None: indexer = np.arange(arr.shape[axis], dtype=np.int64) dtype, fill_value = arr.dtype, arr.dtype.type() diff --git a/pandas/core/base.py b/pandas/core/base.py index 0d55fa8b97aae..9ca1c8bea4db7 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -737,11 +737,17 @@ def item(self): @property def data(self): """ return the data pointer of the underlying data """ + warnings.warn("{obj}.data is deprecated and will be removed " + "in a future version".format(obj=type(self).__name__), + FutureWarning, stacklevel=2) return self.values.data @property def itemsize(self): """ return the size of the dtype of the item of the underlying data """ + warnings.warn("{obj}.itemsize is deprecated and will be removed " + "in a future version".format(obj=type(self).__name__), + FutureWarning, stacklevel=2) return self._ndarray_values.itemsize @property @@ -752,6 +758,9 @@ def nbytes(self): @property def strides(self): """ return the strides of the underlying data """ + warnings.warn("{obj}.strudes is deprecated and will be removed " + "in a future version".format(obj=type(self).__name__), + FutureWarning, stacklevel=2) return self._ndarray_values.strides @property @@ -762,6 +771,9 @@ def size(self): @property def flags(self): """ return the ndarray.flags for the underlying data """ + warnings.warn("{obj}.flags is deprecated and will be removed " + "in a future version".format(obj=type(self).__name__), + FutureWarning, stacklevel=2) return self.values.flags @property @@ -769,6 +781,9 @@ def base(self): """ return the base object if the memory of the underlying data is shared """ + warnings.warn("{obj}.base is deprecated and will be removed " + "in a future version".format(obj=type(self).__name__), + FutureWarning, stacklevel=2) return self.values.base @property diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 21006c4831ac5..2ceec1592d49b 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -550,6 +550,9 @@ def _deepcopy_if_needed(self, orig, copy=False): """ if copy: # Retrieve the "base objects", i.e. the original memory allocations + if not isinstance(orig, np.ndarray): + # orig is a DatetimeIndex + orig = orig.values orig = orig if orig.base is None else orig.base new = self._data if self._data.base is None else self._data.base if orig is new: diff --git a/pandas/core/internals.py b/pandas/core/internals.py index e98899b2f5c1a..a266ea620bd9f 100644 --- a/pandas/core/internals.py +++ b/pandas/core/internals.py @@ -2816,6 +2816,12 @@ def _maybe_coerce_values(self, values, dtype=None): return values + @property + def is_view(self): + """ return a boolean if I am possibly a view """ + # check the ndarray values of the DatetimeIndex values + return self.values.values.base is not None + def copy(self, deep=True, mgr=None): """ copy constructor """ values = self.values diff --git a/pandas/tests/groupby/aggregate/test_other.py b/pandas/tests/groupby/aggregate/test_other.py index 7c6cb5b9615cb..a10f7f6e46210 100644 --- a/pandas/tests/groupby/aggregate/test_other.py +++ b/pandas/tests/groupby/aggregate/test_other.py @@ -328,7 +328,7 @@ def test_series_agg_multi_pure_python(): 'F': np.random.randn(11)}) def bad(x): - assert (len(x.base) > 0) + assert (len(x.values.base) > 0) return 'foo' result = data.groupby(['A', 'B']).agg(bad) diff --git a/pandas/tests/groupby/test_groupby.py b/pandas/tests/groupby/test_groupby.py index bb892f92f213e..e05f9de5ea7f4 100644 --- a/pandas/tests/groupby/test_groupby.py +++ b/pandas/tests/groupby/test_groupby.py @@ -1066,7 +1066,7 @@ def convert_fast(x): def convert_force_pure(x): # base will be length 0 - assert (len(x.base) > 0) + assert (len(x.values.base) > 0) return Decimal(str(x.mean())) grouped = s.groupby(labels) diff --git a/pandas/tests/indexes/common.py b/pandas/tests/indexes/common.py index 758f3f0ef9ebc..f78bd583288a4 100644 --- a/pandas/tests/indexes/common.py +++ b/pandas/tests/indexes/common.py @@ -24,7 +24,7 @@ class Base(object): """ base class for index sub-class tests """ _holder = None - _compat_props = ['shape', 'ndim', 'size', 'itemsize', 'nbytes'] + _compat_props = ['shape', 'ndim', 'size', 'nbytes'] def setup_indices(self): for name, idx in self.indices.items(): diff --git a/pandas/tests/indexes/test_multi.py b/pandas/tests/indexes/test_multi.py index cc006baa64ce6..da11ac645ae07 100644 --- a/pandas/tests/indexes/test_multi.py +++ b/pandas/tests/indexes/test_multi.py @@ -30,7 +30,7 @@ class TestMultiIndex(Base): _holder = MultiIndex - _compat_props = ['shape', 'ndim', 'size', 'itemsize'] + _compat_props = ['shape', 'ndim', 'size'] def setup_method(self, method): major_axis = Index(['foo', 'bar', 'baz', 'qux']) diff --git a/pandas/tests/indexes/test_range.py b/pandas/tests/indexes/test_range.py index 1ebeef072fdc5..8990834ebe91a 100644 --- a/pandas/tests/indexes/test_range.py +++ b/pandas/tests/indexes/test_range.py @@ -22,7 +22,7 @@ class TestRangeIndex(Numeric): _holder = RangeIndex - _compat_props = ['shape', 'ndim', 'size', 'itemsize'] + _compat_props = ['shape', 'ndim', 'size'] def setup_method(self, method): self.indices = dict(index=RangeIndex(0, 20, 2, name='foo'), diff --git a/pandas/tests/internals/test_internals.py b/pandas/tests/internals/test_internals.py index 9338aba90d7cb..7fbf7ec05e91e 100644 --- a/pandas/tests/internals/test_internals.py +++ b/pandas/tests/internals/test_internals.py @@ -466,7 +466,11 @@ def test_copy(self, mgr): # view assertion assert cp_blk.equals(blk) - assert cp_blk.values.base is blk.values.base + if isinstance(blk.values, np.ndarray): + assert cp_blk.values.base is blk.values.base + else: + # DatetimeTZBlock has DatetimeIndex values + assert cp_blk.values.values.base is blk.values.values.base cp = mgr.copy(deep=True) for blk, cp_blk in zip(mgr.blocks, cp.blocks): @@ -474,8 +478,8 @@ def test_copy(self, mgr): # copy assertion we either have a None for a base or in case of # some blocks it is an array (e.g. datetimetz), but was copied assert cp_blk.equals(blk) - if cp_blk.values.base is not None and blk.values.base is not None: - assert cp_blk.values.base is not blk.values.base + if not isinstance(cp_blk.values, np.ndarray): + assert cp_blk.values.values.base is not blk.values.values.base else: assert cp_blk.values.base is None and blk.values.base is None diff --git a/pandas/tests/test_base.py b/pandas/tests/test_base.py index c4c02c0bf6f17..a5d83c1c26948 100644 --- a/pandas/tests/test_base.py +++ b/pandas/tests/test_base.py @@ -316,16 +316,22 @@ def test_ndarray_compat_properties(self): for o in self.objs: # Check that we work. - for p in ['shape', 'dtype', 'flags', 'T', - 'strides', 'itemsize', 'nbytes']: + for p in ['shape', 'dtype', 'T', 'nbytes']: assert getattr(o, p, None) is not None - assert hasattr(o, 'base') + # deprecated properties + for p in ['flags', 'strides', 'itemsize']: + with tm.assert_produces_warning(FutureWarning): + assert getattr(o, p, None) is not None + + with tm.assert_produces_warning(FutureWarning): + assert hasattr(o, 'base') # If we have a datetime-like dtype then needs a view to work # but the user is responsible for that try: - assert o.data is not None + with tm.assert_produces_warning(FutureWarning): + assert o.data is not None except ValueError: pass