diff --git a/doc/source/release.rst b/doc/source/release.rst index 25202dca34a77..03867e3bf6543 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -86,21 +86,10 @@ API Changes - ``df.to_html`` will now print out the header of an empty dataframe (:issue:`6062`) - The ``interpolate`` ``downcast`` keyword default has been changed from ``infer`` to ``None``. This is to preseve the original dtype unless explicitly requested otherwise (:issue:`6290`). -- allow a Series to utilize index methods depending on its index type, e.g. ``Series.year`` is now defined - for a Series with a ``DatetimeIndex`` or a ``PeriodIndex``; trying this on a non-supported Index type will - now raise a ``TypeError``. (:issue:`4551`, :issue:`4056`, :issue:`5519`) - - The following are affected: - - - ``date,time,year,month,day`` - - ``hour,minute,second,weekofyear`` - - ``week,dayofweek,dayofyear,quarter`` - - ``microsecond,nanosecond,qyear`` - - ``is_month_start,is_month_end`` - - ``is_quarter_start,is_quarter_end`` - - ``is_year_start,is_year_end`` - - ``min(),max()`` - - ``pd.infer_freq()`` +- allow ``Series`` and ``Index`` to share common ops. remove the ``Series.weekday`` property from Series; + Using a ``DatetimeIndex/PeriodIndex`` method on a Series will now raise a ``TypeError``. + support ``min(),max(),factorize(),unique(),nunique(),value_counts()`` on ``Index`` types. + (:issue:`4551`, :issue:`4056`, :issue:`5519`, :issue:`6380`, :issue:`7206`). - Add ``is_month_start``, ``is_month_end``, ``is_quarter_start``, ``is_quarter_end``, ``is_year_start``, ``is_year_end`` accessors for ``DateTimeIndex`` / ``Timestamp`` which return a boolean array diff --git a/doc/source/v0.14.0.txt b/doc/source/v0.14.0.txt index 5f9a2711114c2..525b6f123a617 100644 --- a/doc/source/v0.14.0.txt +++ b/doc/source/v0.14.0.txt @@ -73,28 +73,10 @@ API changes ``None``. This is to preseve the original dtype unless explicitly requested otherwise (:issue:`6290`). - When converting a dataframe to HTML it used to return `Empty DataFrame`. This special case has been removed, instead a header with the column names is returned (:issue:`6062`). -- allow a Series to utilize index methods depending on its index type, e.g. ``Series.year`` is now defined - for a Series with a ``DatetimeIndex`` or a ``PeriodIndex``; trying this on a non-supported Index type will - now raise a ``TypeError``. (:issue:`4551`, :issue:`4056`, :issue:`5519`) - - The following are affected: - - - ``date,time,year,month,day`` - - ``hour,minute,second,weekofyear`` - - ``week,dayofweek,dayofyear,quarter`` - - ``microsecond,nanosecond,qyear`` - - ``is_month_start,is_month_end`` - - ``is_quarter_start,is_quarter_end`` - - ``is_year_start,is_year_end`` - - ``min(),max()`` - - ``pd.infer_freq()`` - - .. ipython:: python - - s = Series(np.random.randn(5),index=tm.makeDateIndex(5)) - s - s.year - s.index.year +- allow ``Series`` and ``Index`` to share common ops. remove the ``Series.weekday`` property from Series; + Using a ``DatetimeIndex/PeriodIndex`` method on a Series will now raise a ``TypeError``. + support ``min(),max(),factorize(),unique(),nunique(),value_counts()`` on ``Index`` types. + (:issue:`4551`, :issue:`4056`, :issue:`5519`, :issue:`6380`, :issue:`7206`). - Add ``is_month_start``, ``is_month_end``, ``is_quarter_start``, ``is_quarter_end``, ``is_year_start``, ``is_year_end`` accessors for ``DateTimeIndex`` / ``Timestamp`` which return a boolean array of whether the timestamp(s) are at the start/end of the month/quarter/year defined by the frequency of the ``DateTimeIndex`` / ``Timestamp`` (:issue:`4565`, :issue:`6998`) @@ -355,7 +337,7 @@ are introduced. The function :func:`~pandas.read_sql` is kept as a convenience wrapper around the other two and will delegate to specific function depending on the provided input (database table name or sql query). -In practice, you have to provide a SQLAlchemy ``engine`` to the sql functions. +In practice, you have to provide a SQLAlchemy ``engine`` to the sql functions. To connect with SQLAlchemy you use the :func:`create_engine` function to create an engine object from database URI. You only need to create the engine once per database you are connecting to. For an in-memory sqlite database: @@ -384,7 +366,7 @@ or by specifying a sql query: .. ipython:: python pd.read_sql_query('SELECT * FROM db_table', engine) - + Some other enhancements to the sql functions include: - support for writing the index. This can be controlled with the ``index`` @@ -397,7 +379,7 @@ Some other enhancements to the sql functions include: Some of the existing functions or function aliases have been deprecated and will be removed in future versions. This includes: ``tquery``, ``uquery``, - ``read_frame``, ``frame_query``, ``write_frame``. + ``read_frame``, ``frame_query``, ``write_frame``. .. warning:: @@ -638,7 +620,7 @@ Deprecations - The support for the 'mysql' flavor when using DBAPI connection objects has been deprecated. MySQL will be further supported with SQLAlchemy engines (:issue:`6900`). - - The following ``io.sql`` functions have been deprecated: ``tquery``, ``uquery``, ``read_frame``, ``frame_query``, ``write_frame``. + - The following ``io.sql`` functions have been deprecated: ``tquery``, ``uquery``, ``read_frame``, ``frame_query``, ``write_frame``. - The `percentile_width` keyword argument in :meth:`~DataFrame.describe` has been deprecated. Use the `percentiles` keyword instead, which takes a list of percentiles to display. The diff --git a/pandas/core/base.py b/pandas/core/base.py index 5605e1b0bb7ce..68200f5ed8d31 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -261,12 +261,10 @@ def _wrap_access_object(self, obj): def max(self): """ The maximum value of the object """ - self._is_allowed_index_op('max') return self.values.max() def min(self): """ The minimum value of the object """ - self._is_allowed_index_op('min') return self.values.min() def value_counts(self, normalize=False, sort=True, ascending=False, diff --git a/pandas/core/series.py b/pandas/core/series.py index 1637ba49d86a2..ea3656662ab06 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -121,11 +121,15 @@ class Series(base.IndexOpsMixin, generic.NDFrame): @property def _allow_datetime_index_ops(self): - return self.index.is_all_dates and isinstance(self.index, DatetimeIndex) + # disabling to invalidate datetime index ops (GH7206) + # return self.index.is_all_dates and isinstance(self.index, DatetimeIndex) + return False @property def _allow_period_index_ops(self): - return self.index.is_all_dates and isinstance(self.index, PeriodIndex) + # disabling to invalidate period index ops (GH7206) + # return self.index.is_all_dates and isinstance(self.index, PeriodIndex) + return False def __init__(self, data=None, index=None, dtype=None, name=None, copy=False, fastpath=False): diff --git a/pandas/tests/test_base.py b/pandas/tests/test_base.py index b50f13e84f8f6..49430be8c98a6 100644 --- a/pandas/tests/test_base.py +++ b/pandas/tests/test_base.py @@ -452,7 +452,15 @@ def setUp(self): def test_ops_properties(self): self.check_ops_properties(['year','month','day','hour','minute','second','weekofyear','week','dayofweek','dayofyear','quarter']) - self.check_ops_properties(['date','time','microsecond','nanosecond', 'is_month_start', 'is_month_end', 'is_quarter_start', 'is_quarter_end', 'is_year_start', 'is_year_end'], lambda x: isinstance(x,DatetimeIndex)) + self.check_ops_properties(['date','time','microsecond','nanosecond', 'is_month_start', 'is_month_end', 'is_quarter_start', + 'is_quarter_end', 'is_year_start', 'is_year_end'], lambda x: isinstance(x,DatetimeIndex)) + + def test_ops_properties_basic(self): + + # sanity check that the behavior didn't change + # GH7206 + for op in ['year','day','second','weekday']: + self.assertRaises(TypeError, lambda x: getattr(self.dt_series,op)) class TestPeriodIndexOps(Ops): _allowed = '_allow_period_index_ops' diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index bb7b0a32bbed6..e0ae6a30cbf1a 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -5619,7 +5619,9 @@ def test_asfreq(self): def test_weekday(self): # Just run the function - weekdays = self.ts.weekday + def f(): + self.ts.weekday + self.assertRaises(TypeError, f) def test_diff(self): # Just run the function @@ -5715,7 +5717,7 @@ def test_select(self): assert_series_equal(result, expected) result = self.ts.select(lambda x: x.weekday() == 2) - expected = self.ts[self.ts.weekday == 2] + expected = self.ts[self.ts.index.weekday == 2] assert_series_equal(result, expected) #------------------------------------------------------------------------------