|
12 | 12 | from pandas._libs.tslibs.timestamps import (
|
13 | 13 | RoundTo, maybe_integer_op_deprecated, round_nsint64)
|
14 | 14 | import pandas.compat as compat
|
| 15 | +from pandas.compat.numpy import function as nv |
15 | 16 | from pandas.errors import (
|
16 | 17 | AbstractMethodError, NullFrequencyError, PerformanceWarning)
|
17 | 18 | from pandas.util._decorators import Appender, Substitution, deprecate_kwarg
|
@@ -82,6 +83,79 @@ def _get_attributes_dict(self):
|
82 | 83 | """
|
83 | 84 | return {k: getattr(self, k, None) for k in self._attributes}
|
84 | 85 |
|
| 86 | + @property |
| 87 | + def _scalar_type(self): |
| 88 | + # type: () -> Union[type, Tuple[type]] |
| 89 | + """The scalar associated with this datelike |
| 90 | +
|
| 91 | + * PeriodArray : Period |
| 92 | + * DatetimeArray : Timestamp |
| 93 | + * TimedeltaArray : Timedelta |
| 94 | + """ |
| 95 | + raise AbstractMethodError(self) |
| 96 | + |
| 97 | + def _scalar_from_string(self, value): |
| 98 | + # type: (str) -> Union[Period, Timestamp, Timedelta, NaTType] |
| 99 | + """ |
| 100 | + Construct a scalar type from a string. |
| 101 | +
|
| 102 | + Parameters |
| 103 | + ---------- |
| 104 | + value : str |
| 105 | +
|
| 106 | + Returns |
| 107 | + ------- |
| 108 | + Period, Timestamp, or Timedelta, or NaT |
| 109 | + Whatever the type of ``self._scalar_type`` is. |
| 110 | +
|
| 111 | + Notes |
| 112 | + ----- |
| 113 | + This should call ``self._check_compatible_with`` before |
| 114 | + unboxing the result. |
| 115 | + """ |
| 116 | + raise AbstractMethodError(self) |
| 117 | + |
| 118 | + def _unbox_scalar(self, value): |
| 119 | + # type: (Union[Period, Timestamp, Timedelta, NaTType]) -> int |
| 120 | + """ |
| 121 | + Unbox the integer value of a scalar `value`. |
| 122 | +
|
| 123 | + Parameters |
| 124 | + ---------- |
| 125 | + value : Union[Period, Timestamp, Timedelta] |
| 126 | +
|
| 127 | + Returns |
| 128 | + ------- |
| 129 | + int |
| 130 | +
|
| 131 | + Examples |
| 132 | + -------- |
| 133 | + >>> self._unbox_scalar(Timedelta('10s')) # DOCTEST: +SKIP |
| 134 | + 10000000000 |
| 135 | + """ |
| 136 | + raise AbstractMethodError(self) |
| 137 | + |
| 138 | + def _check_compatible_with(self, other): |
| 139 | + # type: (Union[Period, Timestamp, Timedelta, NaTType]) -> None |
| 140 | + """ |
| 141 | + Verify that `self` and `other` are compatible. |
| 142 | +
|
| 143 | + * DatetimeArray verifies that the timezones (if any) match |
| 144 | + * PeriodArray verifies that the freq matches |
| 145 | + * Timedelta has no verification |
| 146 | +
|
| 147 | + In each case, NaT is considered compatible. |
| 148 | +
|
| 149 | + Parameters |
| 150 | + ---------- |
| 151 | + other |
| 152 | +
|
| 153 | + Raises |
| 154 | + ------ |
| 155 | + Exception |
| 156 | + """ |
| 157 | + raise AbstractMethodError(self) |
| 158 | + |
85 | 159 |
|
86 | 160 | class DatelikeOps(object):
|
87 | 161 | """
|
@@ -515,6 +589,67 @@ def _values_for_factorize(self):
|
515 | 589 | def _from_factorized(cls, values, original):
|
516 | 590 | return cls(values, dtype=original.dtype)
|
517 | 591 |
|
| 592 | + def _values_for_argsort(self): |
| 593 | + return self._data |
| 594 | + |
| 595 | + # ------------------------------------------------------------------ |
| 596 | + # Additional array methods |
| 597 | + # These are not part of the EA API, but we implement them because |
| 598 | + # pandas assumes they're there. |
| 599 | + |
| 600 | + def searchsorted(self, value, side='left', sorter=None): |
| 601 | + """ |
| 602 | + Find indices where elements should be inserted to maintain order. |
| 603 | +
|
| 604 | + Find the indices into a sorted array `self` such that, if the |
| 605 | + corresponding elements in `value` were inserted before the indices, |
| 606 | + the order of `self` would be preserved. |
| 607 | +
|
| 608 | + Parameters |
| 609 | + ---------- |
| 610 | + value : array_like |
| 611 | + Values to insert into `self`. |
| 612 | + side : {'left', 'right'}, optional |
| 613 | + If 'left', the index of the first suitable location found is given. |
| 614 | + If 'right', return the last such index. If there is no suitable |
| 615 | + index, return either 0 or N (where N is the length of `self`). |
| 616 | + sorter : 1-D array_like, optional |
| 617 | + Optional array of integer indices that sort `self` into ascending |
| 618 | + order. They are typically the result of ``np.argsort``. |
| 619 | +
|
| 620 | + Returns |
| 621 | + ------- |
| 622 | + indices : array of ints |
| 623 | + Array of insertion points with the same shape as `value`. |
| 624 | + """ |
| 625 | + if isinstance(value, compat.string_types): |
| 626 | + value = self._scalar_from_string(value) |
| 627 | + |
| 628 | + if not (isinstance(value, (self._scalar_type, type(self))) |
| 629 | + or isna(value)): |
| 630 | + raise ValueError("Unexpected type for 'value': {valtype}" |
| 631 | + .format(valtype=type(value))) |
| 632 | + |
| 633 | + self._check_compatible_with(value) |
| 634 | + if isinstance(value, type(self)): |
| 635 | + value = value.asi8 |
| 636 | + else: |
| 637 | + value = self._unbox_scalar(value) |
| 638 | + |
| 639 | + return self.asi8.searchsorted(value, side=side, sorter=sorter) |
| 640 | + |
| 641 | + def repeat(self, repeats, *args, **kwargs): |
| 642 | + """ |
| 643 | + Repeat elements of an array. |
| 644 | +
|
| 645 | + See Also |
| 646 | + -------- |
| 647 | + numpy.ndarray.repeat |
| 648 | + """ |
| 649 | + nv.validate_repeat(args, kwargs) |
| 650 | + values = self._data.repeat(repeats) |
| 651 | + return type(self)(values, dtype=self.dtype) |
| 652 | + |
518 | 653 | # ------------------------------------------------------------------
|
519 | 654 | # Null Handling
|
520 | 655 |
|
|
0 commit comments