diff --git a/doc/source/basics.rst b/doc/source/basics.rst index e880bb2d6b952..81c2dfd4311f9 100644 --- a/doc/source/basics.rst +++ b/doc/source/basics.rst @@ -1125,7 +1125,7 @@ This enables nice expressions like this: .. ipython:: python # period - s = Series(period_range('20130101',periods=4,freq='D').asobject) + s = Series(period_range('20130101',periods=4,freq='D')) s s.dt.year s.dt.day diff --git a/doc/source/v0.15.0.txt b/doc/source/v0.15.0.txt index 496230bd5f3a1..d26f0e56a9b57 100644 --- a/doc/source/v0.15.0.txt +++ b/doc/source/v0.15.0.txt @@ -102,7 +102,7 @@ API changes 2 6 3 NaN dtype: float64 - + New behavior (note final value is ``5 = sum([2, 3, NaN])``): .. ipython:: python @@ -139,7 +139,7 @@ API changes 4 1.571429 5 2.189189 dtype: float64 - + New behavior (note values start at index ``4``, the location of the 2nd (since ``min_periods=2``) non-empty value): .. ipython:: python @@ -369,7 +369,7 @@ This enables nice expressions like this: .. ipython:: python # period - s = Series(period_range('20130101',periods=4,freq='D').asobject) + s = Series(period_range('20130101',periods=4,freq='D')) s s.dt.year s.dt.day @@ -593,7 +593,7 @@ Bug Fixes - Bug in Panel when using ``major_xs`` and ``copy=False`` is passed (deprecation warning fails because of missing ``warnings``) (:issue:`8152`). - Bug in pickle deserialization that failed for pre-0.14.1 containers with dup items trying to avoid ambiguity when matching block and manager items, when there's only one block there's no ambiguity (:issue:`7794`) - +- Bug in putting a ``PeriodIndex`` into a ``Series`` would convert to ``int64`` dtype, rather than ``object`` of ``Periods`` (:issue:`7932`) - Bug in HDFStore iteration when passing a where (:issue:`8014`) - Bug in DataFrameGroupby.transform when transforming with a passed non-sorted key (:issue:`8046`) - Bug in repeated timeseries line and area plot may result in ``ValueError`` or incorrect kind (:issue:`7733`) diff --git a/pandas/core/algorithms.py b/pandas/core/algorithms.py index 4abb6ed10d6a7..ee9854f8dc5f9 100644 --- a/pandas/core/algorithms.py +++ b/pandas/core/algorithms.py @@ -196,8 +196,9 @@ def value_counts(values, sort=True, ascending=False, normalize=False, """ from pandas.core.series import Series from pandas.tools.tile import cut + from pandas.tseries.period import PeriodIndex - is_period = getattr(values, 'inferred_type', None) == 'period' + is_period = com.is_period_arraylike(values) values = Series(values).values is_category = com.is_categorical_dtype(values.dtype) @@ -215,6 +216,9 @@ def value_counts(values, sort=True, ascending=False, normalize=False, dtype = values.dtype if issubclass(values.dtype.type, (np.datetime64, np.timedelta64)) or is_period: + if is_period: + values = PeriodIndex(values) + values = values.view(np.int64) keys, counts = htable.value_count_int64(values) diff --git a/pandas/core/common.py b/pandas/core/common.py index e3a0cf14cfbc1..692388e60065a 100644 --- a/pandas/core/common.py +++ b/pandas/core/common.py @@ -2325,6 +2325,13 @@ def is_iterator(obj): def is_number(obj): return isinstance(obj, (numbers.Number, np.number)) +def is_period_arraylike(arr): + """ return if we are period arraylike / PeriodIndex """ + if isinstance(arr, pd.PeriodIndex): + return True + elif isinstance(arr, (np.ndarray, ABCSeries)): + return arr.dtype == object and lib.infer_dtype(arr) == 'period' + return getattr(arr, 'inferred_type', None) == 'period' def _coerce_to_dtype(dtype): """ coerce a string / np.dtype to a dtype """ @@ -2380,7 +2387,6 @@ def is_datetime64_ns_dtype(arr_or_dtype): tipo = _get_dtype(arr_or_dtype) return tipo == _NS_DTYPE - def is_timedelta64_dtype(arr_or_dtype): tipo = _get_dtype_type(arr_or_dtype) return issubclass(tipo, np.timedelta64) diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index da4dc904c71e3..64a83ce3c3137 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -110,7 +110,7 @@ def get_expected(s, name): tm.assert_series_equal(s.dt.second,Series(np.array([0,1,2],dtype='int64'),index=index)) # periodindex - for s in [Series(period_range('20130101',periods=5,freq='D').asobject)]: + for s in [Series(period_range('20130101',periods=5,freq='D'))]: for prop in ok_for_period: tm.assert_series_equal(getattr(s.dt,prop),get_expected(s,prop)) @@ -747,6 +747,15 @@ def test_constructor_dtype_datetime64(self): s = Series([pd.NaT, np.nan, '2013-08-05 15:30:00.000001']) self.assertEqual(s.dtype,'datetime64[ns]') + def test_constructor_periodindex(self): + # GH7932 + # converting a PeriodIndex when put in a Series + + pi = period_range('20130101',periods=5,freq='D') + s = Series(pi) + expected = Series(pi.asobject) + assert_series_equal(s, expected) + def test_constructor_dict(self): d = {'a': 0., 'b': 1., 'c': 2.} result = Series(d, index=['b', 'c', 'd', 'a']) diff --git a/pandas/tseries/common.py b/pandas/tseries/common.py index 92ccd1248fac9..d3b86d73dca3a 100644 --- a/pandas/tseries/common.py +++ b/pandas/tseries/common.py @@ -39,15 +39,9 @@ def maybe_to_datetimelike(data, copy=False): if issubclass(data.dtype.type, np.datetime64): return DatetimeProperties(DatetimeIndex(data, copy=copy), index) else: - - if isinstance(data, PeriodIndex): + if com.is_period_arraylike(data): return PeriodProperties(PeriodIndex(data, copy=copy), index) - data = com._values_from_object(data) - inferred = lib.infer_dtype(data) - if inferred == 'period': - return PeriodProperties(PeriodIndex(data), index) - raise TypeError("cannot convert an object of type {0} to a datetimelike index".format(type(data))) class Properties(PandasDelegate): diff --git a/pandas/tseries/frequencies.py b/pandas/tseries/frequencies.py index edc7b075da6f8..873d24530d1d9 100644 --- a/pandas/tseries/frequencies.py +++ b/pandas/tseries/frequencies.py @@ -664,9 +664,10 @@ def infer_freq(index, warn=True): if not (com.is_datetime64_dtype(index.values) or values.dtype == object): raise TypeError("cannot infer freq from a non-convertible dtype on a Series of {0}".format(index.dtype)) index = values - if isinstance(index, pd.PeriodIndex): + + if com.is_period_arraylike(index): raise TypeError("PeriodIndex given. Check the `freq` attribute " - "instead of using infer_freq.") + "instead of using infer_freq.") if isinstance(index, pd.Index) and not isinstance(index, pd.DatetimeIndex): if isinstance(index, (pd.Int64Index, pd.Float64Index)): raise TypeError("cannot infer freq from a non-convertible index type {0}".format(type(index))) diff --git a/pandas/tseries/period.py b/pandas/tseries/period.py index dfea3e0486d32..942a2f445fd48 100644 --- a/pandas/tseries/period.py +++ b/pandas/tseries/period.py @@ -746,6 +746,10 @@ def __contains__(self, key): def _box_func(self): return lambda x: Period._from_ordinal(ordinal=x, freq=self.freq) + def _to_embed(self, keep_tz=False): + """ return an array repr of this object, potentially casting to object """ + return self.asobject.values + def asof_locs(self, where, mask): """ where : array of timestamps