123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- """
- frozen (immutable) data structures to support MultiIndexing
- These are used for:
- - .names (FrozenList)
- - .levels & .codes (FrozenNDArray)
- """
- import warnings
- import numpy as np
- from pandas.util._decorators import deprecate_kwarg
- from pandas.core.dtypes.cast import coerce_indexer_dtype
- from pandas.core.base import PandasObject
- from pandas.io.formats.printing import pprint_thing
- class FrozenList(PandasObject, list):
- """
- Container that doesn't allow setting item *but*
- because it's technically non-hashable, will be used
- for lookups, appropriately, etc.
- """
- # Side note: This has to be of type list. Otherwise,
- # it messes up PyTables type checks.
- def union(self, other):
- """
- Returns a FrozenList with other concatenated to the end of self.
- Parameters
- ----------
- other : array-like
- The array-like whose elements we are concatenating.
- Returns
- -------
- diff : FrozenList
- The collection difference between self and other.
- """
- if isinstance(other, tuple):
- other = list(other)
- return type(self)(super(FrozenList, self).__add__(other))
- def difference(self, other):
- """
- Returns a FrozenList with elements from other removed from self.
- Parameters
- ----------
- other : array-like
- The array-like whose elements we are removing self.
- Returns
- -------
- diff : FrozenList
- The collection difference between self and other.
- """
- other = set(other)
- temp = [x for x in self if x not in other]
- return type(self)(temp)
- # TODO: Consider deprecating these in favor of `union` (xref gh-15506)
- __add__ = __iadd__ = union
- # Python 2 compat
- def __getslice__(self, i, j):
- return self.__class__(super(FrozenList, self).__getslice__(i, j))
- def __getitem__(self, n):
- # Python 3 compat
- if isinstance(n, slice):
- return self.__class__(super(FrozenList, self).__getitem__(n))
- return super(FrozenList, self).__getitem__(n)
- def __radd__(self, other):
- if isinstance(other, tuple):
- other = list(other)
- return self.__class__(other + list(self))
- def __eq__(self, other):
- if isinstance(other, (tuple, FrozenList)):
- other = list(other)
- return super(FrozenList, self).__eq__(other)
- __req__ = __eq__
- def __mul__(self, other):
- return self.__class__(super(FrozenList, self).__mul__(other))
- __imul__ = __mul__
- def __reduce__(self):
- return self.__class__, (list(self),)
- def __hash__(self):
- return hash(tuple(self))
- def _disabled(self, *args, **kwargs):
- """This method will not function because object is immutable."""
- raise TypeError("'%s' does not support mutable operations." %
- self.__class__.__name__)
- def __unicode__(self):
- return pprint_thing(self, quote_strings=True,
- escape_chars=('\t', '\r', '\n'))
- def __repr__(self):
- return "%s(%s)" % (self.__class__.__name__,
- str(self))
- __setitem__ = __setslice__ = __delitem__ = __delslice__ = _disabled
- pop = append = extend = remove = sort = insert = _disabled
- class FrozenNDArray(PandasObject, np.ndarray):
- # no __array_finalize__ for now because no metadata
- def __new__(cls, data, dtype=None, copy=False):
- warnings.warn("\nFrozenNDArray is deprecated and will be removed in a "
- "future version.\nPlease use `numpy.ndarray` instead.\n",
- FutureWarning, stacklevel=2)
- if copy is None:
- copy = not isinstance(data, FrozenNDArray)
- res = np.array(data, dtype=dtype, copy=copy).view(cls)
- return res
- def _disabled(self, *args, **kwargs):
- """This method will not function because object is immutable."""
- raise TypeError("'%s' does not support mutable operations." %
- self.__class__)
- __setitem__ = __setslice__ = __delitem__ = __delslice__ = _disabled
- put = itemset = fill = _disabled
- def _shallow_copy(self):
- return self.view()
- def values(self):
- """returns *copy* of underlying array"""
- arr = self.view(np.ndarray).copy()
- return arr
- def __unicode__(self):
- """
- Return a string representation for this object.
- Invoked by unicode(df) in py2 only. Yields a Unicode String in both
- py2/py3.
- """
- prepr = pprint_thing(self, escape_chars=('\t', '\r', '\n'),
- quote_strings=True)
- return "%s(%s, dtype='%s')" % (type(self).__name__, prepr, self.dtype)
- @deprecate_kwarg(old_arg_name="v", new_arg_name="value")
- def searchsorted(self, value, side="left", sorter=None):
- """
- Find indices to insert `value` so as to maintain order.
- For full documentation, see `numpy.searchsorted`
- See Also
- --------
- numpy.searchsorted : Equivalent function.
- """
- # We are much more performant if the searched
- # indexer is the same type as the array.
- #
- # This doesn't matter for int64, but DOES
- # matter for smaller int dtypes.
- #
- # xref: https://github.com/numpy/numpy/issues/5370
- try:
- value = self.dtype.type(value)
- except ValueError:
- pass
- return super(FrozenNDArray, self).searchsorted(
- value, side=side, sorter=sorter)
- def _ensure_frozen(array_like, categories, copy=False):
- array_like = coerce_indexer_dtype(array_like, categories)
- array_like = array_like.view(FrozenNDArray)
- if copy:
- array_like = array_like.copy()
- return array_like
|