예제 #1
0
    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)}).'
            )
예제 #2
0
    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))
예제 #3
0
    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)
예제 #4
0
        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)
예제 #5
0
        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)
예제 #6
0
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
예제 #7
0
        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)
예제 #8
0
    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))
예제 #9
0
    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)