Skip to content

Commit 90d2f37

Browse files
committed
BUG: PeriodIndex.unique results in Int64Index
1 parent a23c6c7 commit 90d2f37

File tree

4 files changed

+38
-26
lines changed

4 files changed

+38
-26
lines changed

doc/source/v0.15.0.txt

+2
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ Bug Fixes
274274

275275
- Bug in ``is_superperiod`` and ``is_subperiod`` cannot handle higher frequencies than ``S`` (:issue:`7760`, :issue:`7772`, :issue:`7803`)
276276

277+
- Bug in ``PeriodIndex.unique`` returns int64 ``np.ndarray`` (:issue:`7540`)
278+
277279
- Bug in ``DataFrame.reset_index`` which has ``MultiIndex`` contains ``PeriodIndex`` or ``DatetimeIndex`` with tz raises ``ValueError`` (:issue:`7746`, :issue:`7793`)
278280

279281

pandas/core/base.py

+14
Original file line numberDiff line numberDiff line change
@@ -552,3 +552,17 @@ def __sub__(self, other):
552552

553553
def _add_delta(self, other):
554554
return NotImplemented
555+
556+
def unique(self):
557+
"""
558+
Index.unique with handling for DatetimeIndex/PeriodIndex metadata
559+
560+
Returns
561+
-------
562+
result : DatetimeIndex or PeriodIndex
563+
"""
564+
from pandas.core.index import Int64Index
565+
result = Int64Index.unique(self)
566+
return self._simple_new(result, name=self.name, freq=self.freq,
567+
tz=getattr(self, 'tz', None))
568+

pandas/tests/test_base.py

+22-14
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,13 @@ def test_value_counts_unique_nunique(self):
250250
expected_s = Series(range(10, 0, -1), index=values[::-1], dtype='int64')
251251
tm.assert_series_equal(o.value_counts(), expected_s)
252252

253-
if isinstance(o, DatetimeIndex):
254-
# DatetimeIndex.unique returns DatetimeIndex
255-
self.assertTrue(o.unique().equals(klass(values)))
256-
else:
257-
self.assert_numpy_array_equal(o.unique(), values)
253+
result = o.unique()
254+
if isinstance(o, (DatetimeIndex, PeriodIndex)):
255+
self.assertTrue(isinstance(result, o.__class__))
256+
self.assertEqual(result.name, o.name)
257+
self.assertEqual(result.freq, o.freq)
258+
259+
self.assert_numpy_array_equal(result, values)
258260

259261
self.assertEqual(o.nunique(), len(np.unique(o.values)))
260262

@@ -263,17 +265,13 @@ def test_value_counts_unique_nunique(self):
263265
klass = type(o)
264266
values = o.values
265267

266-
if o.values.dtype == 'int64':
267-
# skips int64 because it doesn't allow to include nan or None
268-
continue
269-
270268
if ((isinstance(o, Int64Index) and not isinstance(o,
271269
(DatetimeIndex, PeriodIndex)))):
272270
# skips int64 because it doesn't allow to include nan or None
273271
continue
274272

275273
# special assign to the numpy array
276-
if o.values.dtype == 'datetime64[ns]':
274+
if o.values.dtype == 'datetime64[ns]' or isinstance(o, PeriodIndex):
277275
values[0:2] = pd.tslib.iNaT
278276
else:
279277
values[0:2] = null_obj
@@ -294,8 +292,8 @@ def test_value_counts_unique_nunique(self):
294292
result = o.unique()
295293
self.assert_numpy_array_equal(result[1:], values[2:])
296294

297-
if isinstance(o, DatetimeIndex):
298-
self.assertTrue(result[0] is pd.NaT)
295+
if isinstance(o, (DatetimeIndex, PeriodIndex)):
296+
self.assertTrue(result.asi8[0] == pd.tslib.iNaT)
299297
else:
300298
self.assertTrue(pd.isnull(result[0]))
301299

@@ -706,7 +704,7 @@ def test_sub_isub(self):
706704
rng -= 1
707705
tm.assert_index_equal(rng, expected)
708706

709-
def test_value_counts(self):
707+
def test_value_counts_unique(self):
710708
# GH 7735
711709
for tz in [None, 'UTC', 'Asia/Tokyo', 'US/Eastern']:
712710
idx = pd.date_range('2011-01-01 09:00', freq='H', periods=10)
@@ -717,6 +715,9 @@ def test_value_counts(self):
717715
expected = Series(range(10, 0, -1), index=exp_idx, dtype='int64')
718716
tm.assert_series_equal(idx.value_counts(), expected)
719717

718+
expected = pd.date_range('2011-01-01 09:00', freq='H', periods=10, tz=tz)
719+
tm.assert_index_equal(idx.unique(), expected)
720+
720721
idx = DatetimeIndex(['2013-01-01 09:00', '2013-01-01 09:00', '2013-01-01 09:00',
721722
'2013-01-01 08:00', '2013-01-01 08:00', pd.NaT], tz=tz)
722723

@@ -728,6 +729,8 @@ def test_value_counts(self):
728729
expected = Series([3, 2, 1], index=exp_idx)
729730
tm.assert_series_equal(idx.value_counts(dropna=False), expected)
730731

732+
tm.assert_index_equal(idx.unique(), exp_idx)
733+
731734

732735
class TestPeriodIndexOps(Ops):
733736
_allowed = '_allow_period_index_ops'
@@ -987,7 +990,7 @@ def test_sub_isub(self):
987990
rng -= 1
988991
tm.assert_index_equal(rng, expected)
989992

990-
def test_value_counts(self):
993+
def test_value_counts_unique(self):
991994
# GH 7735
992995
idx = pd.period_range('2011-01-01 09:00', freq='H', periods=10)
993996
# create repeated values, 'n'th element is repeated by n+1 times
@@ -1000,6 +1003,9 @@ def test_value_counts(self):
10001003
expected = Series(range(10, 0, -1), index=exp_idx, dtype='int64')
10011004
tm.assert_series_equal(idx.value_counts(), expected)
10021005

1006+
expected = pd.period_range('2011-01-01 09:00', freq='H', periods=10)
1007+
tm.assert_index_equal(idx.unique(), expected)
1008+
10031009
idx = PeriodIndex(['2013-01-01 09:00', '2013-01-01 09:00', '2013-01-01 09:00',
10041010
'2013-01-01 08:00', '2013-01-01 08:00', pd.NaT], freq='H')
10051011

@@ -1011,6 +1017,8 @@ def test_value_counts(self):
10111017
expected = Series([3, 2, 1], index=exp_idx)
10121018
tm.assert_series_equal(idx.value_counts(dropna=False), expected)
10131019

1020+
tm.assert_index_equal(idx.unique(), exp_idx)
1021+
10141022

10151023
if __name__ == '__main__':
10161024
import nose

pandas/tseries/index.py

-12
Original file line numberDiff line numberDiff line change
@@ -848,18 +848,6 @@ def take(self, indices, axis=0):
848848
return self[maybe_slice]
849849
return super(DatetimeIndex, self).take(indices, axis)
850850

851-
def unique(self):
852-
"""
853-
Index.unique with handling for DatetimeIndex metadata
854-
855-
Returns
856-
-------
857-
result : DatetimeIndex
858-
"""
859-
result = Int64Index.unique(self)
860-
return DatetimeIndex._simple_new(result, tz=self.tz,
861-
name=self.name)
862-
863851
def union(self, other):
864852
"""
865853
Specialized union for DatetimeIndex objects. If combine

0 commit comments

Comments
 (0)