|
28 | 28 | from pandas.core.dtypes.missing import isna
|
29 | 29 |
|
30 | 30 | from pandas.core import nanops
|
31 |
| -from pandas.core.algorithms import checked_add_with_arr, take, unique1d |
| 31 | +from pandas.core.algorithms import ( |
| 32 | + checked_add_with_arr, take, unique1d, value_counts) |
32 | 33 | import pandas.core.common as com
|
33 | 34 |
|
34 | 35 | from pandas.tseries import frequencies
|
35 | 36 | from pandas.tseries.offsets import DateOffset, Tick
|
36 | 37 |
|
37 |
| -from .base import ExtensionOpsMixin |
| 38 | +from .base import ExtensionArray, ExtensionOpsMixin |
38 | 39 |
|
39 | 40 |
|
40 | 41 | def _make_comparison_op(cls, op):
|
@@ -343,7 +344,9 @@ def ceil(self, freq, ambiguous='raise', nonexistent='raise'):
|
343 | 344 | return self._round(freq, RoundTo.PLUS_INFTY, ambiguous, nonexistent)
|
344 | 345 |
|
345 | 346 |
|
346 |
| -class DatetimeLikeArrayMixin(ExtensionOpsMixin, AttributesMixin): |
| 347 | +class DatetimeLikeArrayMixin(ExtensionOpsMixin, |
| 348 | + AttributesMixin, |
| 349 | + ExtensionArray): |
347 | 350 | """
|
348 | 351 | Shared Base/Mixin class for DatetimeArray, TimedeltaArray, PeriodArray
|
349 | 352 |
|
@@ -701,6 +704,43 @@ def repeat(self, repeats, *args, **kwargs):
|
701 | 704 | values = self._data.repeat(repeats)
|
702 | 705 | return type(self)(values.view('i8'), dtype=self.dtype)
|
703 | 706 |
|
| 707 | + def value_counts(self, dropna=False): |
| 708 | + """ |
| 709 | + Return a Series containing counts of unique values. |
| 710 | +
|
| 711 | + Parameters |
| 712 | + ---------- |
| 713 | + dropna : boolean, default True |
| 714 | + Don't include counts of NaT values. |
| 715 | +
|
| 716 | + Returns |
| 717 | + ------- |
| 718 | + Series |
| 719 | + """ |
| 720 | + from pandas import Series, Index |
| 721 | + |
| 722 | + if dropna: |
| 723 | + values = self[~self.isna()]._data |
| 724 | + else: |
| 725 | + values = self._data |
| 726 | + |
| 727 | + cls = type(self) |
| 728 | + |
| 729 | + result = value_counts(values, sort=False, dropna=dropna) |
| 730 | + index = Index(cls(result.index.view('i8'), dtype=self.dtype), |
| 731 | + name=result.index.name) |
| 732 | + return Series(result.values, index=index, name=result.name) |
| 733 | + |
| 734 | + def map(self, mapper): |
| 735 | + # TODO(GH-23179): Add ExtensionArray.map |
| 736 | + # Need to figure out if we want ExtensionArray.map first. |
| 737 | + # If so, then we can refactor IndexOpsMixin._map_values to |
| 738 | + # a standalone function and call from here.. |
| 739 | + # Else, just rewrite _map_infer_values to do the right thing. |
| 740 | + from pandas import Index |
| 741 | + |
| 742 | + return Index(self).map(mapper).array |
| 743 | + |
704 | 744 | # ------------------------------------------------------------------
|
705 | 745 | # Null Handling
|
706 | 746 |
|
@@ -1357,10 +1397,9 @@ def _reduce(self, name, axis=0, skipna=True, **kwargs):
|
1357 | 1397 | if op:
|
1358 | 1398 | return op(axis=axis, skipna=skipna, **kwargs)
|
1359 | 1399 | else:
|
1360 |
| - raise TypeError("cannot perform {name} with type {dtype}" |
1361 |
| - .format(name=name, dtype=self.dtype)) |
1362 |
| - # TODO: use super(DatetimeLikeArrayMixin, self)._reduce |
1363 |
| - # after we subclass ExtensionArray |
| 1400 | + return super(DatetimeLikeArrayMixin, self)._reduce( |
| 1401 | + name, skipna, **kwargs |
| 1402 | + ) |
1364 | 1403 |
|
1365 | 1404 | def min(self, axis=None, skipna=True, *args, **kwargs):
|
1366 | 1405 | """
|
|
0 commit comments