def pivot_items_to_frame( *, blocks: TypeBlocks, group_fields_iloc: tp.Iterable[tp.Hashable], group_depth: int, data_field_iloc: tp.Hashable, func_single: tp.Optional[UFunc], frame_cls: tp.Type['Frame'], name: NameType, dtype: np.dtype, index_constructor: IndexConstructor, columns_constructor: IndexConstructor, kind: str, ) -> 'Frame': ''' Specialized generator of pairs for when we have only one data_field and one function. This version returns a Frame. ''' from static_frame.core.series import Series group_key = group_fields_iloc if group_depth > 1 else group_fields_iloc[ 0] #type: ignore if func_single: labels = [] values = [] for label, _, v in blocks.group_extract( axis=0, key=group_key, extract=data_field_iloc, kind=kind, ): labels.append(label) values.append(func_single(v)) if dtype is None: array, _ = iterable_to_array_1d(values, count=len(values)) else: array = np.array(values, dtype=dtype) array.flags.writeable = False index = index_constructor(labels) return frame_cls.from_elements( array, index=index, own_index=True, columns=(name, ), columns_constructor=columns_constructor, ) # func_no scenario if group_depth == 1: index = index_constructor(blocks._extract_array_column(group_key)) else: index = index_constructor( tuple(label) for label in blocks._extract_array(column_key=group_key)) array = blocks._extract_array_column(data_field_iloc) return frame_cls.from_elements( array, index=index, own_index=True, columns=(name, ), columns_constructor=columns_constructor, )
def pivot_items_to_block( *, blocks: TypeBlocks, group_fields_iloc: tp.Iterable[tp.Hashable], group_depth: int, data_field_iloc: tp.Hashable, func_single: tp.Optional[UFunc], dtype: tp.Optional[np.dtype], fill_value: tp.Any, fill_value_dtype: np.dtype, index_outer: 'IndexBase', kind: str, ) -> np.ndarray: ''' Specialized generator of pairs for when we have only one data_field and one function. ''' from static_frame.core.series import Series group_key = group_fields_iloc if group_depth > 1 else group_fields_iloc[ 0] #type: ignore if func_single and dtype is not None: array = np.full( len(index_outer), fill_value, dtype=resolve_dtype(dtype, fill_value_dtype), ) for label, _, values in blocks.group_extract( axis=0, key=group_key, extract=data_field_iloc, kind=kind, ): array[index_outer._loc_to_iloc(label)] = func_single(values) array.flags.writeable = False return array if func_single and dtype is None: def gen() -> tp.Iterator[tp.Tuple[int, tp.Any]]: for label, _, values in blocks.group_extract( axis=0, key=group_key, extract=data_field_iloc, kind=kind, ): yield index_outer._loc_to_iloc(label), func_single(values) post = Series.from_items(gen()) if len(post) == len(index_outer): array = np.empty(len(index_outer), dtype=post.dtype) else: array = np.full( len(index_outer), fill_value, dtype=resolve_dtype(post.dtype, fill_value_dtype), ) array[post.index.values] = post.values array.flags.writeable = False return array # func_no scenario as no mapping here if group_depth == 1: labels = [ index_outer._loc_to_iloc(label) for label in blocks._extract_array_column(group_key) ] else: # NOTE: might replace _extract_array_column with an iterator of tuples labels = [ index_outer._loc_to_iloc(tuple(label)) for label in blocks._extract_array(column_key=group_key) ] values = blocks._extract_array_column(data_field_iloc) if len(values) == len(index_outer): array = np.empty(len(index_outer), dtype=dtype) else: array = np.full( len(index_outer), fill_value, dtype=resolve_dtype(values.dtype, fill_value_dtype), ) array[labels] = values array.flags.writeable = False return array