def __init__( self, series: tp.Union[Series, tp.Iterable[Bus]], *, index: tp.Optional[tp.Union[IndexBase, IndexAutoFactoryType]] = None, index_constructor: tp.Optional[IndexConstructor] = None, deepcopy_from_bus: bool = False, hierarchy: tp.Optional[IndexHierarchy] = None, own_index: bool = False, ) -> None: ''' Args: series: An iterable (or :obj:`Series`) of :obj:`Bus`. The length of this container is not the same as ``index``, if provided. index: Optionally provide an index for the :obj:`Frame` contained in all :obj:`Bus`. index_constructor: deepcopy_from_bus: hierarchy: own_index: ''' if isinstance(series, Series): if series.dtype != DTYPE_OBJECT: raise ErrorInitYarn( f'Series passed to initializer must have dtype object, not {series.dtype}' ) self._series = series # Bus by Bus label else: self._series = Series(series, dtype=DTYPE_OBJECT) # get a default index self._deepcopy_from_bus = deepcopy_from_bus # _hierarchy might be None while we still need to set self._index if hierarchy is None: self._hierarchy = buses_to_hierarchy( self._series.values, self._series.index, deepcopy_from_bus=self._deepcopy_from_bus, init_exception_cls=ErrorInitYarn, ) else: self._hierarchy = hierarchy if own_index: self._index = index #type: ignore elif index is None or index is IndexAutoFactory: self._index = IndexAutoFactory.from_optional_constructor( len(self._hierarchy), default_constructor=Index, explicit_constructor=index_constructor) else: # an iterable of labels or an Index self._index = index_from_optional_constructor( index, #type: ignore default_constructor=Index, explicit_constructor=index_constructor) if len(self._index) != len(self._hierarchy): raise ErrorInitYarn( f'Length of supplied index ({len(self._index)}) not of sufficient size ({len(self._hierarchy)}).' )
def test_index_from_optional_constructor_b(self) -> None: idx0 = IndexHierarchy.from_labels([('a', 0), ('a', 1), ('b', 0), ('b', 1)]) idx1 = index_from_optional_constructor( idx0, default_constructor=IndexHierarchy.from_labels) # Since the default constructo is static, we should be able to reuse the index self.assertEqual(id(idx0), id(idx1))
def test_index_from_optional_constructor_a(self) -> None: idx1 = index_from_optional_constructor([1, 3, 4], default_constructor=Index) self.assertEqual(idx1.__class__, Index) # given a mutable index and an immutable default, get immutable version idx2 = index_from_optional_constructor(IndexGO((1, 3, 4)), default_constructor=Index) self.assertEqual(idx2.__class__, Index) # given a mutable index and an immutable default, get immutable version idx3 = index_from_optional_constructor(IndexGO((1, 3, 4)), default_constructor=IndexGO) self.assertEqual(idx3.__class__, IndexGO) # given a mutable index and an immutable default, get immutable version idx4 = index_from_optional_constructor(IndexSecond((1, 3, 4)), default_constructor=Index) self.assertEqual(idx4.__class__, IndexSecond)
def get_index(labels, depth: int): if index_constructors: explicit_constructor = index_constructors[depth] else: explicit_constructor = None return index_from_optional_constructor( labels, default_constructor=cls._INDEX_CONSTRUCTOR, explicit_constructor=explicit_constructor)
def get_index(labels: IndexInitializer, depth: int) -> IndexBase: explicit_constructor: tp.Optional[IndexConstructor] if index_constructors is not None: explicit_constructor = index_constructors[depth] else: explicit_constructor = None return index_from_optional_constructor(labels, default_constructor=cls._INDEX_CONSTRUCTOR, explicit_constructor=explicit_constructor)
def pivot_outer_index( frame: 'Frame', index_fields: tp.Sequence[tp.Hashable], index_depth: int, index_constructor: IndexConstructor = None, ) -> IndexBase: index_loc = index_fields if index_depth > 1 else index_fields[0] if index_depth == 1: index_values = ufunc_unique1d( frame._blocks._extract_array_column( frame._columns._loc_to_iloc(index_loc)), ) index_values.flags.writeable = False name = index_fields[0] index_inner = index_from_optional_constructor( index_values, default_constructor=partial(Index, name=name), explicit_constructor=None if index_constructor is None else partial(index_constructor, name=name), ) else: # > 1 # NOTE: this might force type an undesirable consolidation index_values = ufunc_unique(frame._blocks._extract_array( column_key=frame._columns._loc_to_iloc(index_loc)), axis=0) index_values.flags.writeable = False # NOTE: if index_types need to be provided to an IH here, they must be partialed in the single-argument index_constructor name = tuple(index_fields) index_inner = index_from_optional_constructor( # type: ignore index_values, default_constructor=partial( IndexHierarchy._from_arrays, name=name, ), explicit_constructor=None if index_constructor is None else partial(index_constructor, name=name), ).flat() return index_inner
def get_index(labels: IndexInitializer, depth: int) -> Index: explicit_constructor: tp.Optional[IndexConstructor] if index_constructors is None: explicit_constructor = None elif callable(index_constructors): explicit_constructor = index_constructors # it is a single callable else: # it is a sequence explicit_constructor = index_constructors[depth] return index_from_optional_constructor( labels, #type: ignore default_constructor=cls._INDEX_CONSTRUCTOR, explicit_constructor=explicit_constructor)
def from_index_items( cls: tp.Type[IH], items: tp.Iterable[tp.Tuple[tp.Hashable, Index]], *, index_constructor: tp.Optional[IndexConstructor] = None) -> IH: ''' Given an iterable of pairs of label, :obj:`Index`, produce an :obj:`IndexHierarchy` where the labels are depth 0, the indices are depth 1. Args: items: iterable of pairs of label, :obj:`Index`. index_constructor: Optionally provide index constructor for outermost index. ''' labels = [] index_levels = [] offset = 0 for label, index in items: labels.append(label) index = mutable_immutable_index_filter(cls.STATIC, index) index_levels.append( cls._LEVEL_CONSTRUCTOR(index, offset=offset, own_index=True)) offset += len(index) targets = ArrayGO(np.array(index_levels, dtype=object), own_iterable=True) index_outer = index_from_optional_constructor( labels, default_constructor=cls._INDEX_CONSTRUCTOR, explicit_constructor=index_constructor) return cls( cls._LEVEL_CONSTRUCTOR(index=index_outer, targets=targets, own_index=True))
def __init__( self, frames: tp.Optional[tp.Iterable[tp.Union[Frame, tp.Type[FrameDeferred]]]], *, index: IndexInitializer, index_constructor: IndexConstructor = None, name: NameType = NAME_DEFAULT, store: tp.Optional[Store] = None, config: StoreConfigMapInitializer = None, max_persist: tp.Optional[int] = None, own_index: bool = False, own_data: bool = False, ): ''' Default Bus constructor. {args} ''' if max_persist is not None: # use an (ordered) dictionary to give use an ordered set, simply pointing to None for all keys self._last_accessed: tp.Dict[tp.Hashable, None] = {} if own_index: self._index = index #type: ignore else: self._index = index_from_optional_constructor( index, default_constructor=Index, explicit_constructor=index_constructor) count = len(self._index) frames_array: np.ndarray if frames is None: if store is None: raise ErrorInitBus( 'Cannot initialize a :obj:`Bus` with neither `frames` nor `store`.' ) self._values_mutable = np.full(count, FrameDeferred, dtype=DTYPE_OBJECT) self._loaded = np.full(count, False, dtype=DTYPE_BOOL) self._loaded_all = False else: if frames.__class__ is np.ndarray: if frames.dtype != DTYPE_OBJECT: #type: ignore raise ErrorInitBus( f'Series passed to initializer must have dtype object, not {frames.dtype}' ) #type: ignore frames_array = frames load_array = False else: if own_data: raise ErrorInitBus( 'Cannot use `own_data` when not supplying an array.') frames_array = np.empty(count, dtype=DTYPE_OBJECT) load_array = True self._loaded = np.empty(count, dtype=DTYPE_BOOL) # do a one time iteration of series for i, (label, value) in enumerate( zip_longest( index, frames, fillvalue=ZIP_LONGEST_DEFAULT, )): if label is ZIP_LONGEST_DEFAULT or value is ZIP_LONGEST_DEFAULT: raise ErrorInitBus( 'frames and index are not of equal length') if load_array: frames_array[i] = value if value is FrameDeferred: self._loaded[i] = False elif isinstance(value, Frame): # permit FrameGO? if max_persist is not None: self._last_accessed[label] = None self._loaded[i] = True else: raise ErrorInitBus( f'supplied {value.__class__} is not a Frame or FrameDeferred.' ) self._loaded_all = self._loaded.all() if own_data or load_array: self._values_mutable = frames_array else: self._values_mutable = frames_array.copy() self._values_mutable.flags.writeable = True # self._index = index self._name = None if name is NAME_DEFAULT else name self._store = store # Not handling cases of max_persist being greater than the length of the Series (might floor to length) if max_persist is not None and max_persist < self._loaded.sum(): raise ErrorInitBus( 'max_persist cannot be less than the number of already loaded Frames' ) self._max_persist = max_persist # providing None will result in default; providing a StoreConfig or StoreConfigMap will return an appropriate map self._config = StoreConfigMap.from_initializer(config)