From 9e67f4370ebf4d63ae65878f5dde6e8371538134 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Tue, 3 Oct 2017 04:25:45 -0700 Subject: [PATCH 1/6] Remove unused imports (#17745) --- pandas/_libs/hashtable.pyx | 6 ------ pandas/_libs/lib.pyx | 6 +----- pandas/_libs/period.pyx | 12 +++--------- pandas/_libs/tslib.pyx | 8 -------- 4 files changed, 4 insertions(+), 28 deletions(-) diff --git a/pandas/_libs/hashtable.pyx b/pandas/_libs/hashtable.pyx index 9aeb700dd5923..b6b81055f89b2 100644 --- a/pandas/_libs/hashtable.pyx +++ b/pandas/_libs/hashtable.pyx @@ -50,12 +50,6 @@ cnp.import_ufunc() cdef int64_t iNaT = util.get_nat() _SIZE_HINT_LIMIT = (1 << 20) + 7 -cdef extern from "datetime.h": - bint PyDateTime_Check(object o) - void PyDateTime_IMPORT() - -PyDateTime_IMPORT - cdef size_t _INIT_VEC_CAP = 128 diff --git a/pandas/_libs/lib.pyx b/pandas/_libs/lib.pyx index 503badd0ca8bc..e7e92b7ae987a 100644 --- a/pandas/_libs/lib.pyx +++ b/pandas/_libs/lib.pyx @@ -48,7 +48,6 @@ cdef double NAN = nan # this is our tseries.pxd from datetime cimport ( get_timedelta64_value, get_datetime64_value, - npy_timedelta, npy_datetime, PyDateTime_Check, PyDate_Check, PyTime_Check, PyDelta_Check, PyDateTime_IMPORT) @@ -62,11 +61,8 @@ from interval import Interval cdef int64_t NPY_NAT = util.get_nat() -ctypedef unsigned char UChar - cimport util -from util cimport (is_array, _checknull, _checknan, INT64_MAX, - INT64_MIN, UINT8_MAX) +from util cimport is_array, _checknull, _checknan cdef extern from "math.h": double sqrt(double x) diff --git a/pandas/_libs/period.pyx b/pandas/_libs/period.pyx index 725da22104efc..7760df5144117 100644 --- a/pandas/_libs/period.pyx +++ b/pandas/_libs/period.pyx @@ -7,8 +7,7 @@ from cpython cimport ( PyObject_RichCompareBool, Py_EQ, Py_NE) -from numpy cimport (int8_t, int32_t, int64_t, import_array, ndarray, - NPY_INT64, NPY_DATETIME, NPY_TIMEDELTA) +from numpy cimport int64_t, import_array, ndarray import numpy as np import_array() @@ -23,12 +22,11 @@ from datetime cimport ( pandas_datetimestruct, pandas_datetimestruct_to_datetime, pandas_datetime_to_datetimestruct, - PANDAS_FR_ns, - INT32_MIN) + PANDAS_FR_ns) cimport util -from util cimport is_period_object, is_string_object +from util cimport is_period_object, is_string_object, INT32_MIN from lib cimport is_null_datetimelike from pandas._libs import tslib @@ -90,12 +88,8 @@ cdef extern from "period_helper.h": int microseconds, int picoseconds, int freq) nogil except INT32_MIN - int64_t get_python_ordinal(int64_t period_ordinal, - int freq) except INT32_MIN - int get_date_info(int64_t ordinal, int freq, date_info *dinfo) nogil except INT32_MIN - double getAbsTime(int, int64_t, int64_t) int pyear(int64_t ordinal, int freq) except INT32_MIN int pqyear(int64_t ordinal, int freq) except INT32_MIN diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index ff20ea287bd9d..745632cf3d719 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -21,7 +21,6 @@ from cpython cimport ( cdef extern from "Python.h": cdef PyTypeObject *Py_TYPE(object) -# this is our datetime.pxd from libc.stdlib cimport free from util cimport (is_integer_object, is_float_object, is_datetime64_object, @@ -65,11 +64,8 @@ from .tslibs.parsing import parse_datetime_string cimport cython -import time - from pandas.compat import iteritems, callable -import operator import collections import warnings @@ -933,10 +929,6 @@ cdef int64_t _NS_UPPER_BOUND = INT64_MAX # use the smallest value with a 0 nanosecond unit (0s in last 3 digits) cdef int64_t _NS_LOWER_BOUND = -9223372036854775000 -cdef pandas_datetimestruct _NS_MIN_DTS, _NS_MAX_DTS -pandas_datetime_to_datetimestruct(_NS_LOWER_BOUND, PANDAS_FR_ns, &_NS_MIN_DTS) -pandas_datetime_to_datetimestruct(_NS_UPPER_BOUND, PANDAS_FR_ns, &_NS_MAX_DTS) - # Resolution is in nanoseconds Timestamp.min = Timestamp(_NS_LOWER_BOUND) Timestamp.max = Timestamp(_NS_UPPER_BOUND) From 2ff1241fa794231b8317ebe96b66f71dce99e0c2 Mon Sep 17 00:00:00 2001 From: Jeff Reback Date: Tue, 3 Oct 2017 09:01:05 -0400 Subject: [PATCH 2/6] TST: remove warnings, xref #15747 (#17761) --- pandas/tests/series/test_indexing.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pandas/tests/series/test_indexing.py b/pandas/tests/series/test_indexing.py index 86211612a5955..09ba0e197438d 100644 --- a/pandas/tests/series/test_indexing.py +++ b/pandas/tests/series/test_indexing.py @@ -854,11 +854,15 @@ def test_basic_getitem_with_labels(self): s = Series(np.random.randn(10), index=lrange(0, 20, 2)) inds = [0, 2, 5, 7, 8] arr_inds = np.array([0, 2, 5, 7, 8]) - result = s[inds] + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + result = s[inds] expected = s.reindex(inds) assert_series_equal(result, expected) - result = s[arr_inds] + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + result = s[arr_inds] expected = s.reindex(arr_inds) assert_series_equal(result, expected) From 50c1dda3f1e0c0a4e439c73ac12943536cf58806 Mon Sep 17 00:00:00 2001 From: gfyoung Date: Tue, 3 Oct 2017 11:14:44 -0700 Subject: [PATCH 3/6] MAINT: DataFramee --> DataFrame in whatsnew --- doc/source/whatsnew/v0.21.0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index 0d4eaa90d7ab3..e47926d95d2fa 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -786,7 +786,7 @@ Plotting - Bug when plotting ``timedelta`` and ``datetime`` dtypes on y-axis (:issue:`16953`) - Line plots no longer assume monotonic x data when calculating xlims, they show the entire lines now even for unsorted x data. (:issue:`11310`, :issue:`11471`) - With matplotlib 2.0.0 and above, calculation of x limits for line plots is left to matplotlib, so that its new default settings are applied. (:issue:`15495`) -- Bug in ``Series.plot.bar`` or ``DataFramee.plot.bar`` with ``y`` not respecting user-passed ``color`` (:issue:`16822`) +- Bug in ``Series.plot.bar`` or ``DataFrame.plot.bar`` with ``y`` not respecting user-passed ``color`` (:issue:`16822`) - Bug causing ``plotting.parallel_coordinates`` to reset the random seed when using random colors (:issue:`17525`) From 9ac7c51faf15bfef0756f9ab50cef3177d7fe5a8 Mon Sep 17 00:00:00 2001 From: gfyoung Date: Tue, 3 Oct 2017 12:49:07 -0700 Subject: [PATCH 4/6] COMPAT: Suppress .take() warning for numpy < 1.12 (#17764) Follow-up to gh-17352. --- pandas/tests/sparse/test_series.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pandas/tests/sparse/test_series.py b/pandas/tests/sparse/test_series.py index 8c0ed322028e8..13dab68b2e5b4 100644 --- a/pandas/tests/sparse/test_series.py +++ b/pandas/tests/sparse/test_series.py @@ -9,7 +9,8 @@ import numpy as np import pandas as pd -from pandas import Series, DataFrame, bdate_range, isna, compat +from pandas import (Series, DataFrame, bdate_range, + isna, compat, _np_version_under1p12) from pandas.tseries.offsets import BDay import pandas.util.testing as tm from pandas.compat import range @@ -527,8 +528,13 @@ def test_numpy_take(self): sp = SparseSeries([1.0, 2.0, 3.0]) indices = [1, 2] - tm.assert_series_equal(np.take(sp, indices, axis=0).to_dense(), - np.take(sp.to_dense(), indices, axis=0)) + # gh-17352: older versions of numpy don't properly + # pass in arguments to downstream .take() implementations. + warning = FutureWarning if _np_version_under1p12 else None + + with tm.assert_produces_warning(warning, check_stacklevel=False): + tm.assert_series_equal(np.take(sp, indices, axis=0).to_dense(), + np.take(sp.to_dense(), indices, axis=0)) msg = "the 'out' parameter is not supported" tm.assert_raises_regex(ValueError, msg, np.take, From 69024a0110fdc5d8e8a015ea2c5316826e2f80be Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Tue, 3 Oct 2017 12:57:05 -0700 Subject: [PATCH 5/6] Explicitly define cmp_pandas_datetimestruct (#17750) --- pandas/_libs/src/datetime/np_datetime.c | 4 ++-- pandas/_libs/src/datetime/np_datetime.h | 8 ++++++++ setup.py | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/pandas/_libs/src/datetime/np_datetime.c b/pandas/_libs/src/datetime/np_datetime.c index ffb901981f939..f8254ed9d8418 100644 --- a/pandas/_libs/src/datetime/np_datetime.c +++ b/pandas/_libs/src/datetime/np_datetime.c @@ -269,8 +269,8 @@ static void set_datetimestruct_days(npy_int64 days, /* * Compares two pandas_datetimestruct objects chronologically */ -int cmp_pandas_datetimestruct(pandas_datetimestruct *a, - pandas_datetimestruct *b) { +int cmp_pandas_datetimestruct(const pandas_datetimestruct *a, + const pandas_datetimestruct *b) { if (a->year > b->year) { return 1; } else if (a->year < b->year) { diff --git a/pandas/_libs/src/datetime/np_datetime.h b/pandas/_libs/src/datetime/np_datetime.h index a20bff60126aa..af3d2e0f01c1b 100644 --- a/pandas/_libs/src/datetime/np_datetime.h +++ b/pandas/_libs/src/datetime/np_datetime.h @@ -99,6 +99,14 @@ convert_datetimestruct_to_datetime(pandas_datetime_metadata *meta, npy_int64 get_datetimestruct_days(const pandas_datetimestruct *dts); + +/* + * Compares two pandas_datetimestruct objects chronologically + */ +int cmp_pandas_datetimestruct(const pandas_datetimestruct *a, + const pandas_datetimestruct *b); + + /* * Adjusts a datetimestruct based on a minutes offset. Assumes * the current values are valid. diff --git a/setup.py b/setup.py index 793aa089e708f..80be007ba2115 100755 --- a/setup.py +++ b/setup.py @@ -511,7 +511,7 @@ def pxd(name): 'pxdfiles': ['_libs/src/util', '_libs/hashtable'], 'depends': _pxi_dep['join']}, '_libs.reshape': {'pyxfile': '_libs/reshape', - 'depends': _pxi_dep['reshape'], 'include': []}, + 'depends': _pxi_dep['reshape']}, '_libs.interval': {'pyxfile': '_libs/interval', 'pxdfiles': ['_libs/hashtable'], 'depends': _pxi_dep['interval']}, @@ -527,7 +527,7 @@ def pxd(name): 'pandas/_libs/src/parser/io.c']}, '_libs.sparse': {'pyxfile': '_libs/sparse', 'depends': (['pandas/_libs/sparse.pyx'] + - _pxi_dep['sparse']), 'include': []}, + _pxi_dep['sparse'])}, '_libs.testing': {'pyxfile': '_libs/testing', 'depends': ['pandas/_libs/testing.pyx']}, '_libs.hashing': {'pyxfile': '_libs/hashing', From 7dd12ee3eb3bddc62a870c1952f8b151e14197c8 Mon Sep 17 00:00:00 2001 From: Jeff Reback Date: Mon, 2 Oct 2017 07:43:30 -0400 Subject: [PATCH 6/6] DEPR: deprecate .get_value and .set_value for Series, DataFrame, Panel, SparseSeries, SparseDataFrame closes #15269 --- doc/source/whatsnew/v0.21.0.txt | 3 +- pandas/core/frame.py | 30 ++++++++++++-- pandas/core/indexing.py | 10 ++--- pandas/core/panel.py | 26 ++++++++++-- pandas/core/series.py | 26 ++++++++++-- pandas/core/sparse/frame.py | 40 +++++++++++++++++-- pandas/core/sparse/series.py | 25 +++++++++++- pandas/tests/frame/test_api.py | 4 +- pandas/tests/frame/test_constructors.py | 16 ++++++-- pandas/tests/frame/test_indexing.py | 53 ++++++++++++++++++------- pandas/tests/series/test_indexing.py | 16 ++++++-- pandas/tests/sparse/test_frame.py | 20 +++++++--- pandas/tests/sparse/test_series.py | 13 ++++-- pandas/tests/test_panel.py | 25 +++++++----- 14 files changed, 244 insertions(+), 63 deletions(-) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index e47926d95d2fa..043a06d09ab64 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -665,7 +665,8 @@ Deprecations - ``pd.TimeGrouper`` is deprecated in favor of :class:`pandas.Grouper` (:issue:`16747`) - ``cdate_range`` has been deprecated in favor of :func:`bdate_range`, which has gained ``weekmask`` and ``holidays`` parameters for building custom frequency date ranges. See the :ref:`documentation ` for more details (:issue:`17596`) - passing ``categories`` or ``ordered`` kwargs to :func:`Series.astype` is deprecated, in favor of passing a :ref:`CategoricalDtype ` (:issue:`17636`) -- Passing a non-existant column in ``.to_excel(..., columns=)`` is deprecated and will raise a ``KeyError`` in the future (:issue:`17295`) +- Passing a non-existent column in ``.to_excel(..., columns=)`` is deprecated and will raise a ``KeyError`` in the future (:issue:`17295`) +- ``.get_value`` and ``.set_value`` on ``Series``, ``DataFrame``, ``Panel``, ``SparseSeries``, and ``SparseDataFrame`` are deprecated in favor of using ``.iat[]`` or ``.at[]`` accessors (:issue:`15269`) .. _whatsnew_0210.deprecations.argmin_min: diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 01e83821d4524..82c251516548d 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -297,7 +297,8 @@ def _constructor(self): return DataFrame _constructor_sliced = Series - _deprecations = NDFrame._deprecations | frozenset(['sortlevel']) + _deprecations = NDFrame._deprecations | frozenset( + ['sortlevel', 'get_value', 'set_value']) @property def _constructor_expanddim(self): @@ -1918,6 +1919,8 @@ def get_value(self, index, col, takeable=False): """ Quickly retrieve single value at passed column and index + .. deprecated:: 0.21.0 + Parameters ---------- index : row label @@ -1929,6 +1932,14 @@ def get_value(self, index, col, takeable=False): value : scalar value """ + warnings.warn("get_value is deprecated and will be removed " + "in a future release. Please use " + ".at[] or .iat[] accessors instead", FutureWarning, + stacklevel=2) + return self._get_value(index, col, takeable=takeable) + + def _get_value(self, index, col, takeable=False): + if takeable: series = self._iget_item_cache(col) return _maybe_box_datetimelike(series._values[index]) @@ -1944,12 +1955,15 @@ def get_value(self, index, col, takeable=False): # use positional col = self.columns.get_loc(col) index = self.index.get_loc(index) - return self.get_value(index, col, takeable=True) + return self._get_value(index, col, takeable=True) + _get_value.__doc__ = get_value.__doc__ def set_value(self, index, col, value, takeable=False): """ Put single value at passed column and index + .. deprecated:: 0.21.0 + Parameters ---------- index : row label @@ -1963,10 +1977,17 @@ def set_value(self, index, col, value, takeable=False): If label pair is contained, will be reference to calling DataFrame, otherwise a new object """ + warnings.warn("set_value is deprecated and will be removed " + "in a future release. Please use " + ".at[] or .iat[] accessors instead", FutureWarning, + stacklevel=2) + return self._set_value(index, col, value, takeable=takeable) + + def _set_value(self, index, col, value, takeable=False): try: if takeable is True: series = self._iget_item_cache(col) - return series.set_value(index, value, takeable=True) + return series._set_value(index, value, takeable=True) series = self._get_item_cache(col) engine = self.index._engine @@ -1979,6 +2000,7 @@ def set_value(self, index, col, value, takeable=False): self._item_cache.pop(col, None) return self + _set_value.__doc__ = set_value.__doc__ def _ixs(self, i, axis=0): """ @@ -2787,7 +2809,7 @@ def lookup(self, row_labels, col_labels): else: result = np.empty(n, dtype='O') for i, (r, c) in enumerate(zip(row_labels, col_labels)): - result[i] = self.get_value(r, c) + result[i] = self._get_value(r, c) if is_object_dtype(result): result = lib.maybe_convert_objects(result) diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index e977e84702982..a4f2df8167240 100755 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -109,7 +109,7 @@ def __getitem__(self, key): if type(key) is tuple: key = tuple(com._apply_if_callable(x, self.obj) for x in key) try: - values = self.obj.get_value(*key) + values = self.obj._get_value(*key) if is_scalar(values): return values except Exception: @@ -1501,7 +1501,7 @@ def _is_scalar_access(self, key): def _getitem_scalar(self, key): # a fast-path to scalar access # if not, raise - values = self.obj.get_value(*key) + values = self.obj._get_value(*key) return values def _get_partial_string_timestamp_match_key(self, key, labels): @@ -1657,7 +1657,7 @@ def _is_scalar_access(self, key): def _getitem_scalar(self, key): # a fast-path to scalar access # if not, raise - values = self.obj.get_value(*key, takeable=True) + values = self.obj._get_value(*key, takeable=True) return values def _is_valid_integer(self, key, axis): @@ -1814,7 +1814,7 @@ def __getitem__(self, key): raise ValueError('Invalid call for scalar access (getting)!') key = self._convert_key(key) - return self.obj.get_value(*key, takeable=self._takeable) + return self.obj._get_value(*key, takeable=self._takeable) def __setitem__(self, key, value): if isinstance(key, tuple): @@ -1830,7 +1830,7 @@ def __setitem__(self, key, value): '(setting)!') key = list(self._convert_key(key, is_setter=True)) key.append(value) - self.obj.set_value(*key, takeable=self._takeable) + self.obj._set_value(*key, takeable=self._takeable) class _AtIndexer(_ScalarAccessIndexer): diff --git a/pandas/core/panel.py b/pandas/core/panel.py index 68733a3a8b94e..ea2a01b594249 100644 --- a/pandas/core/panel.py +++ b/pandas/core/panel.py @@ -470,6 +470,8 @@ def get_value(self, *args, **kwargs): """ Quickly retrieve single value at (item, major, minor) location + .. deprecated:: 0.21.0 + Parameters ---------- item : item label (panel item) @@ -481,6 +483,13 @@ def get_value(self, *args, **kwargs): ------- value : scalar value """ + warnings.warn("get_value is deprecated and will be removed " + "in a future release. Please use " + ".at[] or .iat[] accessors instead", FutureWarning, + stacklevel=2) + return self._get_value(*args, **kwargs) + + def _get_value(self, *args, **kwargs): nargs = len(args) nreq = self._AXIS_LEN @@ -500,12 +509,15 @@ def get_value(self, *args, **kwargs): else: lower = self._get_item_cache(args[0]) - return lower.get_value(*args[1:], takeable=takeable) + return lower._get_value(*args[1:], takeable=takeable) + _get_value.__doc__ = get_value.__doc__ def set_value(self, *args, **kwargs): """ Quickly set single value at (item, major, minor) location + .. deprecated:: 0.21.0 + Parameters ---------- item : item label (panel item) @@ -520,6 +532,13 @@ def set_value(self, *args, **kwargs): If label combo is contained, will be reference to calling Panel, otherwise a new object """ + warnings.warn("set_value is deprecated and will be removed " + "in a future release. Please use " + ".at[] or .iat[] accessors instead", FutureWarning, + stacklevel=2) + return self._set_value(*args, **kwargs) + + def _set_value(self, *args, **kwargs): # require an arg for each axis and the value nargs = len(args) nreq = self._AXIS_LEN + 1 @@ -540,7 +559,7 @@ def set_value(self, *args, **kwargs): else: lower = self._get_item_cache(args[0]) - lower.set_value(*args[1:], takeable=takeable) + lower._set_value(*args[1:], takeable=takeable) return self except KeyError: axes = self._expand_axes(args) @@ -553,7 +572,8 @@ def set_value(self, *args, **kwargs): if made_bigger: maybe_cast_item(result, args[0], likely_dtype) - return result.set_value(*args) + return result._set_value(*args) + _set_value.__doc__ = set_value.__doc__ def _box_item_values(self, key, values): if self.ndim == values.ndim: diff --git a/pandas/core/series.py b/pandas/core/series.py index 58cac46f63d7e..9b456651da8f8 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -147,7 +147,7 @@ class Series(base.IndexOpsMixin, generic.NDFrame): _metadata = ['name'] _accessors = frozenset(['dt', 'cat', 'str']) _deprecations = generic.NDFrame._deprecations | frozenset( - ['sortlevel', 'reshape']) + ['sortlevel', 'reshape', 'get_value', 'set_value']) _allow_index_ops = True def __init__(self, data=None, index=None, dtype=None, name=None, @@ -902,6 +902,8 @@ def get_value(self, label, takeable=False): """ Quickly retrieve single value at passed index label + .. deprecated:: 0.21.0 + Parameters ---------- index : label @@ -911,9 +913,17 @@ def get_value(self, label, takeable=False): ------- value : scalar value """ + warnings.warn("get_value is deprecated and will be removed " + "in a future release. Please use " + ".at[] or .iat[] accessors instead", FutureWarning, + stacklevel=2) + return self._get_value(label, takeable=takeable) + + def _get_value(self, label, takeable=False): if takeable is True: return _maybe_box_datetimelike(self._values[label]) return self.index.get_value(self._values, label) + _get_value.__doc__ = get_value.__doc__ def set_value(self, label, value, takeable=False): """ @@ -921,6 +931,8 @@ def set_value(self, label, value, takeable=False): new object is created with the label placed at the end of the result index + .. deprecated:: 0.21.0 + Parameters ---------- label : object @@ -935,17 +947,25 @@ def set_value(self, label, value, takeable=False): If label is contained, will be reference to calling Series, otherwise a new object """ + warnings.warn("set_value is deprecated and will be removed " + "in a future release. Please use " + ".at[] or .iat[] accessors instead", FutureWarning, + stacklevel=2) + return self._set_value(label, value, takeable=takeable) + + def _set_value(self, label, value, takeable=False): try: if takeable: self._values[label] = value else: self.index._engine.set_value(self._values, label, value) - return self except KeyError: # set using a non-recursive method self.loc[label] = value - return self + + return self + _set_value.__doc__ = set_value.__doc__ def reset_index(self, level=None, drop=False, name=None, inplace=False): """ diff --git a/pandas/core/sparse/frame.py b/pandas/core/sparse/frame.py index 7aa49efa82f61..7fb7ec8cd33f5 100644 --- a/pandas/core/sparse/frame.py +++ b/pandas/core/sparse/frame.py @@ -5,6 +5,7 @@ from __future__ import division # pylint: disable=E1101,E1103,W0231,E0202 +import warnings from pandas.compat import lmap from pandas import compat import numpy as np @@ -430,19 +431,43 @@ def __getitem__(self, key): else: return self._get_item_cache(key) - @Appender(DataFrame.get_value.__doc__, indents=0) def get_value(self, index, col, takeable=False): + """ + Quickly retrieve single value at passed column and index + + .. deprecated:: 0.21.0 + + Parameters + ---------- + index : row label + col : column label + takeable : interpret the index/col as indexers, default False + + Returns + ------- + value : scalar value + """ + warnings.warn("get_value is deprecated and will be removed " + "in a future release. Please use " + ".at[] or .iat[] accessors instead", FutureWarning, + stacklevel=2) + return self._get_value(index, col, takeable=takeable) + + def _get_value(self, index, col, takeable=False): if takeable is True: series = self._iget_item_cache(col) else: series = self._get_item_cache(col) - return series.get_value(index, takeable=takeable) + return series._get_value(index, takeable=takeable) + _get_value.__doc__ = get_value.__doc__ def set_value(self, index, col, value, takeable=False): """ Put single value at passed column and index + .. deprecated:: 0.21.0 + Parameters ---------- index : row label @@ -460,9 +485,18 @@ def set_value(self, index, col, value, takeable=False): ------- frame : DataFrame """ - dense = self.to_dense().set_value(index, col, value, takeable=takeable) + warnings.warn("set_value is deprecated and will be removed " + "in a future release. Please use " + ".at[] or .iat[] accessors instead", FutureWarning, + stacklevel=2) + return self._set_value(index, col, value, takeable=takeable) + + def _set_value(self, index, col, value, takeable=False): + dense = self.to_dense()._set_value( + index, col, value, takeable=takeable) return dense.to_sparse(kind=self._default_kind, fill_value=self._default_fill_value) + _set_value.__doc__ = set_value.__doc__ def _slice(self, slobj, axis=0, kind=None): if axis == 0: diff --git a/pandas/core/sparse/series.py b/pandas/core/sparse/series.py index 5166dc927989e..b7ba17677069d 100644 --- a/pandas/core/sparse/series.py +++ b/pandas/core/sparse/series.py @@ -426,7 +426,7 @@ def _get_values(self, indexer): return self[indexer] def _set_with_engine(self, key, value): - return self.set_value(key, value) + return self._set_value(key, value) def abs(self): """ @@ -466,6 +466,8 @@ def get_value(self, label, takeable=False): """ Retrieve single value at passed index label + .. deprecated:: 0.21.0 + Parameters ---------- index : label @@ -475,8 +477,17 @@ def get_value(self, label, takeable=False): ------- value : scalar value """ + warnings.warn("get_value is deprecated and will be removed " + "in a future release. Please use " + ".at[] or .iat[] accessors instead", FutureWarning, + stacklevel=2) + + return self._get_value(label, takeable=takeable) + + def _get_value(self, label, takeable=False): loc = label if takeable is True else self.index.get_loc(label) return self._get_val_at(loc) + _get_value.__doc__ = get_value.__doc__ def set_value(self, label, value, takeable=False): """ @@ -484,6 +495,8 @@ def set_value(self, label, value, takeable=False): new object is created with the label placed at the end of the result index + .. deprecated:: 0.21.0 + Parameters ---------- label : object @@ -501,11 +514,18 @@ def set_value(self, label, value, takeable=False): ------- series : SparseSeries """ + warnings.warn("set_value is deprecated and will be removed " + "in a future release. Please use " + ".at[] or .iat[] accessors instead", FutureWarning, + stacklevel=2) + return self._set_value(label, value, takeable=takeable) + + def _set_value(self, label, value, takeable=False): values = self.to_dense() # if the label doesn't exist, we will create a new object here # and possibily change the index - new_values = values.set_value(label, value, takeable=takeable) + new_values = values._set_value(label, value, takeable=takeable) if new_values is not None: values = new_values new_index = values.index @@ -513,6 +533,7 @@ def set_value(self, label, value, takeable=False): kind=self.kind) self._data = SingleBlockManager(values, new_index) self._index = new_index + _set_value.__doc__ = set_value.__doc__ def _set_values(self, key, value): diff --git a/pandas/tests/frame/test_api.py b/pandas/tests/frame/test_api.py index 5ea8230ced41b..be6d81c63ae1e 100644 --- a/pandas/tests/frame/test_api.py +++ b/pandas/tests/frame/test_api.py @@ -69,7 +69,9 @@ def test_getitem_pop_assign_name(self): def test_get_value(self): for idx in self.frame.index: for col in self.frame.columns: - result = self.frame.get_value(idx, col) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + result = self.frame.get_value(idx, col) expected = self.frame[col][idx] tm.assert_almost_equal(result, expected) diff --git a/pandas/tests/frame/test_constructors.py b/pandas/tests/frame/test_constructors.py index d0cd1899a0a3c..7f1cc12ec4277 100644 --- a/pandas/tests/frame/test_constructors.py +++ b/pandas/tests/frame/test_constructors.py @@ -258,8 +258,12 @@ def test_constructor_dict(self): # Dict with None value frame_none = DataFrame(dict(a=None), index=[0]) frame_none_list = DataFrame(dict(a=[None]), index=[0]) - assert frame_none.get_value(0, 'a') is None - assert frame_none_list.get_value(0, 'a') is None + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + assert frame_none.get_value(0, 'a') is None + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + assert frame_none_list.get_value(0, 'a') is None tm.assert_frame_equal(frame_none, frame_none_list) # GH10856 @@ -509,7 +513,9 @@ def test_nested_dict_frame_constructor(self): data = {} for col in df.columns: for row in df.index: - data.setdefault(col, {})[row] = df.get_value(row, col) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + data.setdefault(col, {})[row] = df.get_value(row, col) result = DataFrame(data, columns=rng) tm.assert_frame_equal(result, df) @@ -517,7 +523,9 @@ def test_nested_dict_frame_constructor(self): data = {} for col in df.columns: for row in df.index: - data.setdefault(row, {})[col] = df.get_value(row, col) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + data.setdefault(row, {})[col] = df.get_value(row, col) result = DataFrame(data, index=rng).T tm.assert_frame_equal(result, df) diff --git a/pandas/tests/frame/test_indexing.py b/pandas/tests/frame/test_indexing.py index dd2759cd3ef8e..d00f56830a6fa 100644 --- a/pandas/tests/frame/test_indexing.py +++ b/pandas/tests/frame/test_indexing.py @@ -1629,7 +1629,9 @@ def test_getitem_list_duplicates(self): def test_get_value(self): for idx in self.frame.index: for col in self.frame.columns: - result = self.frame.get_value(idx, col) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + result = self.frame.get_value(idx, col) expected = self.frame[col][idx] assert result == expected @@ -1637,7 +1639,9 @@ def test_lookup(self): def alt(df, rows, cols, dtype): result = [] for r, c in zip(rows, cols): - result.append(df.get_value(r, c)) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + result.append(df.get_value(r, c)) return np.array(result, dtype=dtype) def testit(df): @@ -1671,32 +1675,48 @@ def testit(df): def test_set_value(self): for idx in self.frame.index: for col in self.frame.columns: - self.frame.set_value(idx, col, 1) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + self.frame.set_value(idx, col, 1) assert self.frame[col][idx] == 1 def test_set_value_resize(self): - res = self.frame.set_value('foobar', 'B', 0) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + res = self.frame.set_value('foobar', 'B', 0) assert res is self.frame assert res.index[-1] == 'foobar' - assert res.get_value('foobar', 'B') == 0 + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + assert res.get_value('foobar', 'B') == 0 self.frame.loc['foobar', 'qux'] = 0 - assert self.frame.get_value('foobar', 'qux') == 0 + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + assert self.frame.get_value('foobar', 'qux') == 0 res = self.frame.copy() - res3 = res.set_value('foobar', 'baz', 'sam') + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + res3 = res.set_value('foobar', 'baz', 'sam') assert res3['baz'].dtype == np.object_ res = self.frame.copy() - res3 = res.set_value('foobar', 'baz', True) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + res3 = res.set_value('foobar', 'baz', True) assert res3['baz'].dtype == np.object_ res = self.frame.copy() - res3 = res.set_value('foobar', 'baz', 5) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + res3 = res.set_value('foobar', 'baz', 5) assert is_float_dtype(res3['baz']) assert isna(res3['baz'].drop(['foobar'])).all() - pytest.raises(ValueError, res3.set_value, 'foobar', 'baz', 'sam') + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + pytest.raises(ValueError, res3.set_value, 'foobar', 'baz', 'sam') def test_set_value_with_index_dtype_change(self): df_orig = DataFrame(randn(3, 3), index=lrange(3), columns=list('ABC')) @@ -1704,7 +1724,9 @@ def test_set_value_with_index_dtype_change(self): # this is actually ambiguous as the 2 is interpreted as a positional # so column is not created df = df_orig.copy() - df.set_value('C', 2, 1.0) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + df.set_value('C', 2, 1.0) assert list(df.index) == list(df_orig.index) + ['C'] # assert list(df.columns) == list(df_orig.columns) + [2] @@ -1715,7 +1737,9 @@ def test_set_value_with_index_dtype_change(self): # create both new df = df_orig.copy() - df.set_value('C', 'D', 1.0) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + df.set_value('C', 'D', 1.0) assert list(df.index) == list(df_orig.index) + ['C'] assert list(df.columns) == list(df_orig.columns) + ['D'] @@ -1728,8 +1752,9 @@ def test_get_set_value_no_partial_indexing(self): # partial w/ MultiIndex raise exception index = MultiIndex.from_tuples([(0, 1), (0, 2), (1, 1), (1, 2)]) df = DataFrame(index=index, columns=lrange(4)) - pytest.raises(KeyError, df.get_value, 0, 1) - # pytest.raises(KeyError, df.set_value, 0, 1, 0) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + pytest.raises(KeyError, df.get_value, 0, 1) def test_single_element_ix_dont_upcast(self): self.frame['E'] = 1 diff --git a/pandas/tests/series/test_indexing.py b/pandas/tests/series/test_indexing.py index 09ba0e197438d..ba9fdea8cd53e 100644 --- a/pandas/tests/series/test_indexing.py +++ b/pandas/tests/series/test_indexing.py @@ -800,13 +800,17 @@ def test_setitem_dtypes(self): def test_set_value(self): idx = self.ts.index[10] - res = self.ts.set_value(idx, 0) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + res = self.ts.set_value(idx, 0) assert res is self.ts assert self.ts[idx] == 0 # equiv s = self.series.copy() - res = s.set_value('foobar', 0) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + res = s.set_value('foobar', 0) assert res is s assert res.index[-1] == 'foobar' assert res['foobar'] == 0 @@ -2628,8 +2632,12 @@ def test_series_set_value(self): dates = [datetime(2001, 1, 1), datetime(2001, 1, 2)] index = DatetimeIndex(dates) - s = Series().set_value(dates[0], 1.) - s2 = s.set_value(dates[1], np.nan) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + s = Series().set_value(dates[0], 1.) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + s2 = s.set_value(dates[1], np.nan) exp = Series([1., np.nan], index=index) diff --git a/pandas/tests/sparse/test_frame.py b/pandas/tests/sparse/test_frame.py index ed4a3a9e5f75f..ef94e2f78278d 100644 --- a/pandas/tests/sparse/test_frame.py +++ b/pandas/tests/sparse/test_frame.py @@ -430,22 +430,32 @@ def test_set_value(self): # ok, as the index gets converted to object frame = self.frame.copy() - res = frame.set_value('foobar', 'B', 1.5) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + res = frame.set_value('foobar', 'B', 1.5) assert res.index.dtype == 'object' res = self.frame res.index = res.index.astype(object) - res = self.frame.set_value('foobar', 'B', 1.5) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + res = self.frame.set_value('foobar', 'B', 1.5) assert res is not self.frame assert res.index[-1] == 'foobar' - assert res.get_value('foobar', 'B') == 1.5 + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + assert res.get_value('foobar', 'B') == 1.5 - res2 = res.set_value('foobar', 'qux', 1.5) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + res2 = res.set_value('foobar', 'qux', 1.5) assert res2 is not res tm.assert_index_equal(res2.columns, pd.Index(list(self.frame.columns) + ['qux'])) - assert res2.get_value('foobar', 'qux') == 1.5 + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + assert res2.get_value('foobar', 'qux') == 1.5 def test_fancy_index_misc(self): # axis = 0 diff --git a/pandas/tests/sparse/test_series.py b/pandas/tests/sparse/test_series.py index 13dab68b2e5b4..7c7399317809f 100644 --- a/pandas/tests/sparse/test_series.py +++ b/pandas/tests/sparse/test_series.py @@ -465,15 +465,22 @@ def test_get_get_value(self): expected = self.btseries.to_dense()[dt] tm.assert_almost_equal(result, expected) - tm.assert_almost_equal(self.bseries.get_value(10), self.bseries[10]) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + tm.assert_almost_equal( + self.bseries.get_value(10), self.bseries[10]) def test_set_value(self): idx = self.btseries.index[7] - self.btseries.set_value(idx, 0) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + self.btseries.set_value(idx, 0) assert self.btseries[idx] == 0 - self.iseries.set_value('foobar', 0) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + self.iseries.set_value('foobar', 0) assert self.iseries.index[-1] == 'foobar' assert self.iseries['foobar'] == 0 diff --git a/pandas/tests/test_panel.py b/pandas/tests/test_panel.py index a6113f231f8f2..c8e056f156218 100644 --- a/pandas/tests/test_panel.py +++ b/pandas/tests/test_panel.py @@ -405,7 +405,9 @@ def test_get_value(self): for item in self.panel.items: for mjr in self.panel.major_axis[::2]: for mnr in self.panel.minor_axis: - result = self.panel.get_value(item, mjr, mnr) + with tm.assert_produces_warning(FutureWarning, + check_stacklevel=False): + result = self.panel.get_value(item, mjr, mnr) expected = self.panel[item][mnr][mjr] assert_almost_equal(result, expected) @@ -867,16 +869,17 @@ def test_comp(func): test_comp(operator.le) def test_get_value(self): - for item in self.panel.items: - for mjr in self.panel.major_axis[::2]: - for mnr in self.panel.minor_axis: - result = self.panel.get_value(item, mjr, mnr) - expected = self.panel[item][mnr][mjr] - assert_almost_equal(result, expected) - with tm.assert_raises_regex(TypeError, - "There must be an argument " - "for each axis"): - self.panel.get_value('a') + with catch_warnings(record=True): + for item in self.panel.items: + for mjr in self.panel.major_axis[::2]: + for mnr in self.panel.minor_axis: + result = self.panel.get_value(item, mjr, mnr) + expected = self.panel[item][mnr][mjr] + assert_almost_equal(result, expected) + with tm.assert_raises_regex(TypeError, + "There must be an argument " + "for each axis"): + self.panel.get_value('a') def test_set_value(self): with catch_warnings(record=True):