def test_hierarchy_frame_b(self): OD = OrderedDict tree = OD([ ('I', OD([ ('A', (1,)), ('B', (1, 2)) ]) ), ('II', OD([ ('A', (1,)), ('B', (1, 2)) ]) ), ]) ih = IndexHierarchyGO.from_tree(tree) data = np.arange(6*6).reshape(6, 6) # TODO: this only works if own_columns is True for now f1 = FrameGO(data, index=range(6), columns=ih, own_columns=True) f1[('II', 'B', 3)] = 0 f2 = f1[HLoc[:, 'B']] self.assertEqual(f2.shape, (6, 5)) self.assertEqual(f2.to_pairs(0), ((('I', 'B', 1), ((0, 1), (1, 7), (2, 13), (3, 19), (4, 25), (5, 31))), (('I', 'B', 2), ((0, 2), (1, 8), (2, 14), (3, 20), (4, 26), (5, 32))), (('II', 'B', 1), ((0, 4), (1, 10), (2, 16), (3, 22), (4, 28), (5, 34))), (('II', 'B', 2), ((0, 5), (1, 11), (2, 17), (3, 23), (4, 29), (5, 35))), (('II', 'B', 3), ((0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0)))) ) f3 = f1[HLoc[:, :, 1]] self.assertEqual(f3.to_pairs(0), ((('I', 'A', 1), ((0, 0), (1, 6), (2, 12), (3, 18), (4, 24), (5, 30))), (('I', 'B', 1), ((0, 1), (1, 7), (2, 13), (3, 19), (4, 25), (5, 31))), (('II', 'A', 1), ((0, 3), (1, 9), (2, 15), (3, 21), (4, 27), (5, 33))), (('II', 'B', 1), ((0, 4), (1, 10), (2, 16), (3, 22), (4, 28), (5, 34))))) f4 = f1.loc[[2, 5], HLoc[:, 'A']] self.assertEqual(f4.to_pairs(0), ((('I', 'A', 1), ((2, 12), (5, 30))), (('II', 'A', 1), ((2, 15), (5, 33)))))
def from_pandas(cls, value, *, is_go: bool = False) -> 'IndexBase': ''' Given a Pandas index, return the appropriate IndexBase derived class. ''' import pandas from static_frame import Index from static_frame import IndexGO from static_frame import IndexDate from static_frame import IndexHierarchy from static_frame import IndexHierarchyGO if isinstance(value, pandas.MultiIndex): # iterating over a hierarchucal index will iterate over labels if is_go: return IndexHierarchyGO.from_labels(value) return IndexHierarchy.from_labels(value) elif isinstance(value, pandas.DatetimeIndex): if is_go: raise NotImplementedError( 'No grow-only version of IndexDate yet exists') return IndexDate(value) if is_go: return IndexGO(value) return Index(value)
def from_pandas( cls, value: 'pandas.DataFrame', ) -> 'IndexBase': ''' Given a Pandas index, return the appropriate IndexBase derived class. ''' import pandas from static_frame import Index from static_frame import IndexGO from static_frame import IndexHierarchy from static_frame import IndexHierarchyGO from static_frame import IndexNanosecond from static_frame import IndexNanosecondGO from static_frame.core.index_datetime import IndexDatetime if isinstance(value, pandas.MultiIndex): # iterating over a hierarchucal index will iterate over labels name = tuple(value.names) if not cls.STATIC: return IndexHierarchyGO.from_labels(value, name=name) return IndexHierarchy.from_labels(value, name=name) elif isinstance(value, pandas.DatetimeIndex): # if IndexDatetime, use cls, else use IndexNanosecond if issubclass(cls, IndexDatetime): return cls(value, name=value.name) else: if not cls.STATIC: return IndexNanosecondGO(value, name=value.name) return IndexNanosecond(value, name=value.name) if not cls.STATIC: return IndexGO(value, name=value.name) return Index(value, name=value.name)
def from_pandas(cls, value: 'pandas.DataFrame', ) -> 'IndexBase': ''' Given a Pandas index, return the appropriate IndexBase derived class. ''' import pandas from static_frame.core.index_datetime import IndexDatetime from static_frame import Index from static_frame import IndexGO from static_frame import IndexHierarchy from static_frame import IndexHierarchyGO if isinstance(value, pandas.MultiIndex): # iterating over a hierarchucal index will iterate over labels name = tuple(value.names) if not cls.STATIC: return IndexHierarchyGO.from_labels(value, name=name) return IndexHierarchy.from_labels(value, name=name) elif isinstance(value, pandas.DatetimeIndex): # coming from a Pandas datetime index, in the absence of other information, the best match is a Nanosecond index if not issubclass(cls, IndexDatetime): raise ErrorInitIndex(f'cannot create a datetime Index from {cls}') if not cls.STATIC: return cls(value, name=value.name) return cls(value, name=value.name) if not cls.STATIC: return IndexGO(value, name=value.name) return Index(value, name=value.name)
def test_index_from_optional_constructor_c(self) -> None: idx0 = IndexHierarchyGO.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.assertNotEqual(id(idx0), id(idx1)) self.assertTrue(idx1.STATIC)
def test_hierarchy_from_index_items_b(self) -> None: idx1 = Index(('A', 'B', 'C')) idx2 = Index(('x', 'y')) idx3 = Index((4, 5, 6)) ih = IndexHierarchyGO.from_index_items( dict(a=idx1, b=idx2, c=idx3).items()) ih.append(('c', 7)) self.assertEqual(ih.values.tolist(), [['a', 'A'], ['a', 'B'], ['a', 'C'], ['b', 'x'], ['b', 'y'], ['c', 4], ['c', 5], ['c', 6], ['c', 7]])
def test_hierarchy_index_go_a(self): OD = OrderedDict tree1 = OD([ ('I', OD([('A', (1, )), ('B', (1, 2))])), ('II', OD([('A', (1, )), ('B', (1, 2))])), ]) ih1 = IndexHierarchyGO.from_tree(tree1) tree2 = OD([ ('III', OD([('A', (1, )), ('B', (1, 2))])), ('IV', OD([('A', (1, )), ('B', (1, 2))])), ]) ih2 = IndexHierarchyGO.from_tree(tree2) ih1.extend(ih2) # self.assertEqual(ih1.loc_to_iloc(('IV', 'B', 2)), 11) self.assertEqual(len(ih2), 6) # need tuple here to distinguish from iterable type selection self.assertEqual([ih1.loc_to_iloc(tuple(v)) for v in ih1.values], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
def from_pandas( cls, value: 'pandas.Index', ) -> 'IndexBase': ''' Given a Pandas index, return the appropriate IndexBase derived class. ''' import pandas if not isinstance(value, pandas.Index): raise ErrorInitIndex( f'from_pandas must be called with a Pandas Index object, not: {type(value)}' ) from static_frame import Index from static_frame import IndexGO from static_frame import IndexHierarchy from static_frame import IndexHierarchyGO from static_frame import IndexNanosecond from static_frame import IndexNanosecondGO from static_frame.core.index_datetime import IndexDatetime if isinstance(value, pandas.MultiIndex): # iterating over a hierarchical index will iterate over labels name: tp.Optional[tp.Tuple[tp.Hashable, ...]] = tuple(value.names) # if not assigned Pandas returns None for all components, which will raise issue if trying to unset this index. if all(n is None for n in name): #type: ignore name = None depth = value.nlevels if not cls.STATIC: return IndexHierarchyGO.from_labels(value, name=name, depth_reference=depth) return IndexHierarchy.from_labels(value, name=name, depth_reference=depth) elif isinstance(value, pandas.DatetimeIndex): # if IndexDatetime, use cls, else use IndexNanosecond if issubclass(cls, IndexDatetime): return cls(value, name=value.name) else: if not cls.STATIC: return IndexNanosecondGO(value, name=value.name) return IndexNanosecond(value, name=value.name) if not cls.STATIC: return IndexGO(value, name=value.name) return Index(value, name=value.name)
def test_hierarchy_rehierarch_b(self) -> None: labels = ( ('I', 'A'), ('I', 'B'), ('II', 'C'), ('II', 'B'), ('II', 'D'), ('III', 'D'), ('IV', 'A'), ) ih1 = IndexHierarchyGO.from_labels(labels) self.assertEqual( ih1.rehierarch([1, 0]).values.tolist(), [['A', 'I'], ['A', 'IV'], ['B', 'I'], ['B', 'II'], ['C', 'II'], ['D', 'II'], ['D', 'III']])
def test_hierarchy_from_pandas_c(self): import pandas pdidx = pandas.MultiIndex.from_product((('I', 'II'), ('A', 'B'))) idx = IndexHierarchyGO.from_pandas(pdidx) self.assertEqual(idx.values.tolist(), [['I', 'A'], ['I', 'B'], ['II', 'A'], ['II', 'B']]) self.assertEqual(idx.values.tolist(), [['I', 'A'], ['I', 'B'], ['II', 'A'], ['II', 'B']]) idx.append(('III', 'A')) self.assertEqual( idx.values.tolist(), [['I', 'A'], ['I', 'B'], ['II', 'A'], ['II', 'B'], ['III', 'A']])
def test_hierarchy_name_b(self): idx1 = IndexHierarchyGO.from_product(list('ab'), list('xy'), name='q') idx2 = idx1.rename('w') self.assertEqual(idx1.name, 'q') self.assertEqual(idx2.name, 'w') idx1.append(('c', 'c')) idx2.append(('x', 'x')) self.assertEqual( idx1.values.tolist(), [['a', 'x'], ['a', 'y'], ['b', 'x'], ['b', 'y'], ['c', 'c']]) self.assertEqual( idx2.values.tolist(), [['a', 'x'], ['a', 'y'], ['b', 'x'], ['b', 'y'], ['x', 'x']])
def test_hierarchy_copy_b(self): labels = ( ('I', 'A'), ('I', 'B'), ('II', 'A'), ('II', 'B'), ) ih1 = IndexHierarchyGO.from_labels(labels) ih2 = ih1.copy() ih2.append(('II', 'C')) self.assertEqual( ih2.values.tolist(), [['I', 'A'], ['I', 'B'], ['II', 'A'], ['II', 'B'], ['II', 'C']]) self.assertEqual(ih1.values.tolist(), [['I', 'A'], ['I', 'B'], ['II', 'A'], ['II', 'B']])
def test_hierarchy_keys_a(self) -> None: OD = OrderedDict tree = OD([ ('I', OD([('A', (1, 2)), ('B', (1, 2))])), ('II', OD([('A', (1, 2)), ('B', (1, 2))])), ]) ih = IndexHierarchyGO.from_tree(tree) # NOTE: for now, __iter__ return arrays, so we have convert to a tuple self.assertEqual([tuple(k) in ih.keys() for k in ih], [True, True, True, True, True, True, True, True]) ih.append(('III', 'A', 1)) self.assertEqual( ih.keys(), {('I', 'B', 1), ('I', 'A', 2), ('II', 'B', 2), ('II', 'A', 2), ('I', 'A', 1), ('III', 'A', 1), ('II', 'B', 1), ('II', 'A', 1), ('I', 'B', 2)})