def __init__(self, labels: IndexInitializer, *, loc_is_iloc: bool = False, name: tp.Hashable = None, dtype: DtypeSpecifier = None) -> None: self._recache = False self._map = None positions = None # NOTE: this will not, and shold not, catch IndexHierarchy if issubclass(labels.__class__, Index): # get a reference to the immutable arrays # even if this is an IndexGO index, we can take the cached arrays, assuming they are up to date if labels.STATIC: # can take the map self._map = labels._map if labels._recache: labels._update_array_cache() positions = labels._positions loc_is_iloc = labels._loc_is_iloc if name is None and labels.name is not None: name = labels.name # immutable, so no copy necessary labels = labels._labels self._name = name if name is None else name_filter(name) if self._map is None: self._map = self._get_map(labels, positions) if dtype is None: dtype_extract = self._DTYPE # set in specialized Index classes else: # dtype is not None if self._DTYPE is not None and dtype != self._DTYPE: raise RuntimeError('invalid dtype argument for this Index', dtype, self._DTYPE) # self._DTYPE is None, dtype is not None, use dtype dtype_extract = dtype # this might be NP array, or a list, depending on if static or grow only self._labels = self._extract_labels(self._map, labels, dtype_extract) self._positions = self._extract_positions(self._map, positions) if self._DTYPE and self._labels.dtype != self._DTYPE: raise RuntimeError('invalid label dtype for this Index', self._labels.dtype, self._DTYPE) if len(self._map) != len(self._labels): raise KeyError('labels have non-unique values') # NOTE: automatic discovery is possible, but not yet implemented self._loc_is_iloc = loc_is_iloc
def __init__(self, levels: tp.Union[IndexLevel, 'IndexHierarchy'], *, name: tp.Hashable = None): ''' Args: levels: IndexLevels instance, or, optionally, an IndexHierarchy to be used to construct a new IndexHierarchy. labels: a client can optionally provide the labels used to construct the levels, as an optional optimization in forming the IndexHierarchy. ''' if issubclass(levels.__class__, IndexHierarchy): # handle construction from another IndexHierarchy if self.STATIC and levels.STATIC: self._levels = levels._levels else: # must deepcopy labels if not static; passing level constructor ensures we get a mutable if the parent is mutable self._levels = levels._levels.to_index_level( cls=self._LEVEL_CONSTRUCTOR) self._labels = levels.values self._depth = levels.depth self._keys = levels.keys() # immutable keys view can be shared self._length = self._labels.__len__() self._recache = False if name is None and levels.name is not None: name = levels.name elif isinstance(levels, IndexLevel): # always assume ownership of passed in IndexLevel self._levels = levels # vlaues derived from levels are deferred self._labels = None self._depth = None self._keys = None self._length = None self._recache = True else: raise NotImplementedError( f'no handling for creation from {levels}') self._name = name if name is None else name_filter(name)
def __init__(self, levels: tp.Union[IndexLevel, 'IndexHierarchy'], *, name: tp.Hashable = None): ''' Args: levels: IndexLevels instance, or, optionally, an IndexHierarchy to be used to construct a new IndexHierarchy. labels: a client can optionally provide the labels used to construct the levels, as an optional optimization in forming the IndexHierarchy. ''' if issubclass(levels.__class__, IndexHierarchy): if levels.STATIC: self._levels = levels._levels else: # must deepcopy labels if not static self._levels = levels._levels.to_index_level() self._labels = levels.values self._depth = levels.depth self._keys = levels.keys() # immutable keys view can be shared self._length = self._labels.__len__() #levels.__len__() self._recache = False if name is None and levels.name is not None: name = levels.name elif isinstance(levels, IndexLevel): self._levels = levels # vlaues derived from levels are deferred self._labels = None self._depth = None self._keys = None self._length = None self._recache = True else: raise NotImplementedError('no handling for creation from', levels) self._name = name if name is None else name_filter(name)
def __init__(self, labels: IndexInitializer, *, loc_is_iloc: bool = False, name: tp.Hashable = None, dtype: DtypeSpecifier = None ) -> None: self._recache = False self._map = None positions = None # resolve the targetted labels dtype, by lookin at the class attr _DTYPE and/or the passed dtype argument if dtype is None: dtype_extract = self._DTYPE # set in some specialized Index classes else: # passed dtype is not None if self._DTYPE is not None and dtype != self._DTYPE: raise RuntimeError('invalid dtype argument for this Index', dtype, self._DTYPE) # self._DTYPE is None, passed dtype is not None, use dtype dtype_extract = dtype # handle all Index subclasses # check isinstance(labels, IndexBase) if issubclass(labels.__class__, IndexBase): if labels._recache: labels._update_array_cache() if name is None and labels.name is not None: name = labels.name # immutable, so no copy necessary if labels.depth == 1: # not an IndexHierarchy if labels.STATIC: # can take the map self._map = labels._map # get a reference to the immutable arrays, even if this is an IndexGO index, we can take the cached arrays, assuming they are up to date positions = labels._positions loc_is_iloc = labels._loc_is_iloc labels = labels._labels else: # IndexHierarchy # will be a generator of tuples; already updated caches labels = array2d_to_tuples(labels._labels) elif hasattr(labels, 'values'): # it is a Series or similar array = labels.values if array.ndim == 1: labels = array else: labels = array2d_to_tuples(array) if self._DTYPE is not None: # do not need to check arrays, as will and checked to match dtype_extract in _extract_labels if not isinstance(labels, np.ndarray): # for now, assume that if _DTYPE is defined, we have a date labels = (to_datetime64(v, dtype_extract) for v in labels) else: # coerce to target type labels = labels.astype(dtype_extract) self._name = name if name is None else name_filter(name) if self._map is None: self._map = self._get_map(labels, positions) # this might be NP array, or a list, depending on if static or grow only; if an array, dtype will be compared with passed dtype_extract self._labels = self._extract_labels(self._map, labels, dtype_extract) self._positions = self._extract_positions(self._map, positions) if self._DTYPE and self._labels.dtype != self._DTYPE: raise RuntimeError('invalid label dtype for this Index', self._labels.dtype, self._DTYPE) if len(self._map) != len(self._labels): raise KeyError(f'labels ({len(self._labels)}) have non-unique values ({len(self._map)})') # NOTE: automatic discovery is possible, but not yet implemented self._loc_is_iloc = loc_is_iloc
def __init__(self, values: SeriesInitializer, *, index: IndexInitializer = None, name: tp.Hashable = None, dtype: DtypeSpecifier = None, own_index: bool = False ) -> None: # TODO: support construction from another Series, propagate name attr self._name = name if name is None else name_filter(name) #----------------------------------------------------------------------- # values assignment values_constructor = None # if deferred if not isinstance(values, np.ndarray): if isinstance(values, dict): # not sure if we should sort; not sure what to do if index is provided if index is not None: raise Exception('cannot create a Series from a dictionary when an index is defined') index = [] def values_gen(): for k, v in _dict_to_sorted_items(values): # populate index as side effect of iterating values index.append(k) yield v if dtype and dtype != object: # fromiter does not work with object types self.values = np.fromiter(values_gen(), dtype=dtype, count=len(values)) else: self.values = np.array(tuple(values_gen()), dtype=dtype) self.values.flags.writeable = False # NOTE: not sure if we need to check __iter__ here elif (dtype and dtype != object and dtype != str and hasattr(values, '__iter__') and hasattr(values, '__len__')): self.values = np.fromiter(values, dtype=dtype, count=len(values)) self.values.flags.writeable = False elif hasattr(values, '__len__') and not isinstance(values, str): self.values = np.array(values, dtype=dtype) self.values.flags.writeable = False elif hasattr(values, '__next__'): # a generator-like self.values = np.array(tuple(values), dtype=dtype) self.values.flags.writeable = False else: # it must be a single item # we cannot create the values until we realize the index, which might be hierarchical and not have final size equal to length def values_constructor(shape): self.values = np.full(shape, values, dtype=dtype) self.values.flags.writeable = False else: # is numpy if dtype is not None and dtype != values.dtype: raise Exception('when supplying values via array, the dtype argument is not required; if provided, it must agree with the dtype of the array') if values.shape == (): # handle special case of NP element def values_constructor(shape): self.values = np.repeat(values, shape) self.values.flags.writeable = False else: self.values = immutable_filter(values) #----------------------------------------------------------------------- # index assignment # NOTE: this generally must be done after values assignment, as from_items (for example) needs the values generator to be exhausted before looking to index if index is None or (hasattr(index, '__len__') and len(index) == 0): # create an integer index self._index = Index(range(len(self.values)), loc_is_iloc=True) elif own_index: self._index = index elif hasattr(index, STATIC_ATTR): if index.STATIC: self._index = index else: raise RuntimeError('non-static index cannot be assigned to Series') else: # let index handle instantiation if isinstance(index, (Index, IndexHierarchy)): # call with the class of the passed-in index, in case it is hierarchical self._index = index.__class__(index) else: self._index = Index(index) shape = self._index.__len__() if values_constructor: values_constructor(shape) # updates self.values if len(self.values) != shape: raise RuntimeError('values and index do not match length')
def __init__(self, labels: IndexInitializer, *, loc_is_iloc: bool = False, name: NameType = NAME_DEFAULT, dtype: DtypeSpecifier = None) -> None: self._recache: bool = False self._map: tp.Optional[FrozenAutoMap] = None positions = None is_typed = self._DTYPE is not None # resolve the targetted labels dtype, by lookin at the class attr _DTYPE and/or the passed dtype argument if dtype is None: dtype_extract = self._DTYPE # set in some specialized Index classes else: # passed dtype is not None if is_typed and dtype != self._DTYPE: # NOTE: should never get to this branch, as derived Index classes that set _DTYPE remove dtype from __init__ raise ErrorInitIndex('invalid dtype argument for this Index', dtype, self._DTYPE) #pragma: no cover # self._DTYPE is None, passed dtype is not None, use dtype dtype_extract = dtype #----------------------------------------------------------------------- # handle all Index subclasses if isinstance(labels, IndexBase): if labels._recache: labels._update_array_cache() if name is NAME_DEFAULT: name = labels.name # immutable, so no copy necessary if isinstance(labels, Index): # not an IndexHierarchy if (labels.STATIC and self.STATIC and dtype is None): if not is_typed or (is_typed and self._DTYPE == labels.dtype): # can take the map if static and if types in the dict are the same as those in the labels (or to become the labels after conversion) self._map = labels._map # get a reference to the immutable arrays, even if this is an IndexGO index, we can take the cached arrays, assuming they are up to date; for datetime64 indices, we might need to translate to a different type positions = labels._positions loc_is_iloc = labels._map is None labels = labels._labels else: # IndexHierarchy # will be a generator of tuples; already updated caches labels = array2d_to_tuples(labels.__iter__()) elif isinstance(labels, ContainerOperand): # it is a Series or similar array = labels.values if array.ndim == 1: labels = array else: labels = array2d_to_tuples(array) # else: assume an iterable suitable for labels usage #----------------------------------------------------------------------- if is_typed: # do not need to check arrays, as will and checked to match dtype_extract in _extract_labels if not isinstance(labels, np.ndarray): # for now, assume that if _DTYPE is defined, we have a date labels = (to_datetime64(v, dtype_extract) for v in labels) # coerce to target type elif labels.dtype != dtype_extract: labels = labels.astype(dtype_extract) labels.flags.writeable = False #type: ignore self._name = None if name is NAME_DEFAULT else name_filter(name) if self._map is None: # if _map not shared from another Index if not loc_is_iloc: try: self._map = FrozenAutoMap( labels) if self.STATIC else AutoMap(labels) except ValueError: # Automap will raise ValueError of non-unique values are encountered pass if self._map is None: raise ErrorInitIndex( f'labels ({len(tuple(labels))}) have non-unique values ({len(set(labels))})' ) size = len(self._map) else: # must assume labels are unique # labels must not be a generator, but we assume that internal clients that provided loc_is_iloc will not give a generator size = len(labels) #type: ignore if positions is None: positions = PositionsAllocator.get(size) else: # map shared from another Index size = len(self._map) # this might be NP array, or a list, depending on if static or grow only; if an array, dtype will be compared with passed dtype_extract self._labels = self._extract_labels(self._map, labels, dtype_extract) self._positions = self._extract_positions(size, positions) if self._DTYPE and self._labels.dtype != self._DTYPE: raise ErrorInitIndex( 'invalid label dtype for this Index', #pragma: no cover self._labels.dtype, self._DTYPE)