Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

API: remove datetime-like index ops from Series #7206

Merged
merged 2 commits into from May 22, 2014
Jump to file or symbol
Failed to load files and symbols.
+31 −48
Split
View
@@ -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`).
@jorisvandenbossche

jorisvandenbossche May 22, 2014

Owner

This is a bit cryptic I think. On the one hand you say that Series and Index share common operators, but then you say weekday is removed and datetimeindex methods on a series will raise (so this is not sharing).

Are the changes that are relevant to users not:

  • Series.weekday is removed (and actually should first be deprecated?)
  • min/max/unique/nunique/value_counts methods are added to Index types (that they are shared with Series is an implementation detail, no?)
- 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
View
@@ -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
View
@@ -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,
View
@@ -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):
View
@@ -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'
@@ -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)
#------------------------------------------------------------------------------