def test_index_many_concat_c(self) -> None: from datetime import date i1 = IndexHierarchy.from_labels( [[1, date(2019, 1, 1)], [2, date(2019, 1, 2)]], index_constructors=[Index, IndexDate]) i2 = IndexHierarchy.from_labels( [[2, date(2019, 1, 3)], [3, date(2019, 1, 4)]], index_constructors=[Index, IndexDate]) i3 = IndexHierarchy.from_labels( [[4, date(2019, 1, 5)], [5, date(2019, 1, 6)]], index_constructors=[Index, IndexDate]) i4 = IndexHierarchy.from_labels([[4, date(2019, 1, 5)], [5, date(2019, 1, 6)]]) i5 = index_many_concat((i1, i2, i3), cls_default=Index) assert isinstance(i5, IndexHierarchy) self.assertEqual(i5.index_types.to_pairs(), ((0, Index), (1, IndexDate))) self.assertEqual(i5.values.tolist(), [[1, date(2019, 1, 1)], [2, date(2019, 1, 2)], [2, date(2019, 1, 3)], [3, date(2019, 1, 4)], [4, date(2019, 1, 5)], [5, date(2019, 1, 6)]]) # with unaligned index types we fall back in Index i6 = index_many_concat((i1, i2, i4), cls_default=Index) assert isinstance(i6, IndexHierarchy) self.assertEqual(i6.index_types.to_pairs(), ((0, Index), (1, Index)))
def test_hierarchy_from_labels_e(self) -> None: index_constructors = (Index, IndexDate) labels = ( ('a', '2019-01-01'), ('a', '2019-02-01'), ('b', '2019-01-01'), ('b', '2019-02-01'), ) from static_frame.core.exception import ErrorInitIndex with self.assertRaises(ErrorInitIndex): ih = IndexHierarchy.from_labels(labels, index_constructors=(Index, )) ih = IndexHierarchy.from_labels(labels, index_constructors=index_constructors) self.assertEqual(ih.loc[HLoc[:, '2019-02']].values.tolist(), [['a', datetime.date(2019, 2, 1)], ['b', datetime.date(2019, 2, 1)]]) self.assertEqual(ih.loc[HLoc[:, '2019']].values.tolist(), [['a', datetime.date(2019, 1, 1)], ['a', datetime.date(2019, 2, 1)], ['b', datetime.date(2019, 1, 1)], ['b', datetime.date(2019, 2, 1)]]) self.assertEqual(ih.loc[HLoc[:, '2019-02-01']].values.tolist(), [['a', datetime.date(2019, 2, 1)], ['b', datetime.date(2019, 2, 1)]])
def test_hierarchy_intersection_a(self): labels = ( ('I', 'A'), ('I', 'B'), ('II', 'A'), ('II', 'B'), ) ih1 = IndexHierarchy.from_labels(labels) labels = ( ('II', 'A'), ('II', 'B'), ('III', 'A'), ('III', 'B'), ) ih2 = IndexHierarchy.from_labels(labels) post = ih1.intersection(ih2) self.assertEqual(post.values.tolist(), [['II', 'A'], ['II', 'B']]) post = ih1.union(ih2) self.assertEqual(post.values.tolist(), [['I', 'A'], ['I', 'B'], ['II', 'A'], ['II', 'B'], ['III', 'A'], ['III', 'B']])
def test_hierarchy_from_labels_a(self): labels = ( ('I', 'A', 1), ('I', 'A', 2), ('I', 'B', 1), ('I', 'B', 2), ('II', 'A', 1), ('II', 'A', 2), ('II', 'B', 1), ('II', 'B', 2), ) ih = IndexHierarchy.from_labels(labels) self.assertEqual(len(ih), 8) self.assertEqual(ih.depth, 3) self.assertEqual([ih.loc_to_iloc(x) for x in labels], [0, 1, 2, 3, 4, 5, 6, 7]) labels = ( ('I', 'A', 1), ('I', 'A', 2), ('I', 'B', 1), ('II', 'B', 2), ) ih = IndexHierarchy.from_labels(labels) self.assertEqual(len(ih), 4) self.assertEqual(ih.depth, 3) self.assertEqual([ih.loc_to_iloc(x) for x in labels], [0, 1, 2, 3])
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_many_concat_d(self) -> None: from datetime import date i1 = IndexHierarchy.from_labels( [[1, date(2019, 1, 1)], [2, date(2019, 1, 2)]], index_constructors=[Index, IndexDate]) i2 = IndexHierarchy.from_labels( [[2, date(2019, 1, 3)], [3, date(2019, 1, 4)]], index_constructors=[Index, IndexDate]) post1 = index_many_concat((i1, i2), cls_default=IndexGO) self.assertEqual(post1.__class__, IndexHierarchyGO) assert isinstance(post1, IndexHierarchy) self.assertEqual(post1.values.tolist(), [[1, date(2019, 1, 1)], [2, date(2019, 1, 2)], [2, date(2019, 1, 3)], [3, date(2019, 1, 4)]])
def test_index_level_values_at_depth_a(self) -> None: hidx = IndexHierarchy.from_labels( (('a', 1, 'x'), ('a', 2, 'y'), ('b', 1, 'foo'), ('b', 1, 'bar'))) lvl = hidx._levels self.assertEqual( lvl.values_at_depth(2).tolist(), ['x', 'y', 'foo', 'bar']) self.assertEqual(lvl.depth, next(lvl.depths()))
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 test_hierarchy_contains_a(self): labels = (('I', 'A'), ('I', 'B'), ) ih = IndexHierarchy.from_labels(labels) self.assertTrue(('I', 'A') in ih)
def test_hierarchy_reversed(self): labels = (('a', 1), ('a', 2), ('b', 1), ('b', 2)) hier_idx = IndexHierarchy.from_labels(labels) self.assertTrue( all( tuple(hidx_1) == hidx_2 for hidx_1, hidx_2 in zip( reversed(hier_idx), reversed(labels))))
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 test_hierarchy_relabel_a(self): labels = ( ('I', 'A'), ('I', 'B'), ('II', 'A'), ('II', 'B'), ) ih = IndexHierarchy.from_labels(labels) ih.relabel({('I', 'B'): ('I', 'C')}) ih2 = ih.relabel({('I', 'B'): ('I', 'C')}) self.assertEqual(ih2.values.tolist(), [['I', 'A'], ['I', 'C'], ['II', 'A'], ['II', 'B']]) with self.assertRaises(Exception): ih3 = ih.relabel({('I', 'B'): ('I', 'C', 1)}) ih3 = ih.relabel(lambda x: tuple(e.lower() for e in x)) self.assertEqual(ih3.values.tolist(), [['i', 'a'], ['i', 'b'], ['ii', 'a'], ['ii', 'b']])
def test_index_level_values_at_depth_b(self) -> None: hidx = IndexHierarchy.from_labels( (('a', 1, 'x'), ('a', 2, 'y'), ('b', 1, 'foo'), ('b', 2, None))) #type: ignore lvl = hidx._levels self.assertEqual( lvl.values_at_depth(2).tolist(), ['x', 'y', 'foo', None])
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_hierarhcy_init_c(self): labels = (('I', 'A'), ('I', 'B'), ('II', 'B'), ('III', 'B'), ('III', 'A')) ih1 = IndexHierarchy.from_labels(labels) self.assertEqual( ih1.values.tolist(), [['I', 'A'], ['I', 'B'], ['II', 'B'], ['III', 'B'], ['III', 'A']])
def test_hierarchy_from_labels_b(self): labels = (('I', 'A'), ('I', 'B'), ) ih = IndexHierarchy.from_labels(labels) self.assertEqual(ih.to_frame().to_pairs(0), ((0, ((0, 'I'), (1, 'I'))), (1, ((0, 'A'), (1, 'B')))))
def test_hierarhcy_init_a(self): labels = (('I', 'A'), ('I', 'B'), ) ih1 = IndexHierarchy.from_labels(labels, name='foo') ih2 = IndexHierarchy(ih1) self.assertEqual(ih1.name, 'foo') self.assertEqual(ih2.name, 'foo')
def test_index_level_dtypes_per_depth_a(self) -> None: hidx = IndexHierarchy.from_labels( (('a', 1, 'x'), ('a', 2, 'y'), ('b', 1, 'foo'), ('b', 1, 'bar'))) lvl = hidx._levels self.assertEqual(tuple(lvl.dtypes_at_depth(0)), (np.dtype('<U1'), )) self.assertEqual(tuple(lvl.dtypes_at_depth(1)), (np.dtype('int64'), np.dtype('int64'))) self.assertEqual(tuple(lvl.dtypes_at_depth(2)), (np.dtype('<U1'), np.dtype('<U1'), np.dtype('<U3')))
def test_hierarchy_init_g(self) -> None: labels = ( ('I', 'A', 1), ('I', 'B', 1), ('II', 'A', 1), ('II', 'A', 2), ('II', 'A', 1), ) with self.assertRaises(ErrorInitIndex): ih1 = IndexHierarchy.from_labels(labels)
def test_hierarhcy_init_g(self): labels = ( ('I', 'A', 1), ('I', 'B', 1), ('II', 'A', 1), ('II', 'A', 2), ('II', 'A', 1), ) with self.assertRaises(KeyError): ih1 = IndexHierarchy.from_labels(labels)
def test_hierarhcy_init_b(self): labels = ( ('I', 'A'), ('I', 'B'), ('II', 'B'), ('I', 'C') ) with self.assertRaises(RuntimeError): ih1 = IndexHierarchy.from_labels(labels)
def test_hierarchy_drop_level_d(self): labels = ( ('A', 1), ('B', 2), ('C', 3), ('C', 4), ) ih = IndexHierarchy.from_labels(labels) self.assertEqual(ih.drop_level(1).values.tolist(), [1, 2, 3, 4])
def test_hierarchy_flat_a(self): labels = ( ('I', 'A'), ('I', 'B'), ('II', 'A'), ('II', 'B'), ) ih = IndexHierarchy.from_labels(labels) self.assertEqual(ih.flat().values.tolist(), [('I', 'A'), ('I', 'B'), ('II', 'A'), ('II', 'B')])
def test_index_hierarchy_roll_b(self) -> None: ih1 = IndexHierarchy.from_labels( (('a', 1), ('b', 20), ('c', 400), ('d', 50))) self.assertEqual( ih1.roll(1).values.tolist(), [['d', 50], ['a', 1], ['b', 20], ['c', 400]]) self.assertEqual( ih1.roll(-1).values.tolist(), [['b', 20], ['c', 400], ['d', 50], ['a', 1]])
def test_hierarchy_binary_operators_b(self) -> None: labels = ( (1, 1), (1, 2), ) ih1 = IndexHierarchy.from_labels(labels) labels = ( (3, 3), (1, 2), ) ih2 = IndexHierarchy.from_labels(labels) self.assertEqual((ih1 @ ih2).tolist(), [[4, 5], [5, 7]]) self.assertEqual((ih1.values @ ih2).tolist(), [[4, 5], [5, 7]]) self.assertEqual((ih1 @ ih2.values).tolist(), [[4, 5], [5, 7]]) self.assertEqual((ih1.values @ ih2.values).tolist(), [[4, 5], [5, 7]])
def test_hierarchy_init_f(self) -> None: labels = ( ('I', 'A'), ('I', 'B'), ('II', 'B'), ('III', 'B'), ('I', 'B'), ) with self.assertRaises(RuntimeError): ih1 = IndexHierarchy.from_labels(labels)
def test_hierarchy_drop_level_c(self): labels = ( ('I', 'A', 1), ('I', 'B', 2), ('II', 'C', 3), ('II', 'C', 4), ) ih = IndexHierarchy.from_labels(labels) self.assertEqual(ih.drop_level(1).values.tolist(), [['A', 1], ['B', 2], ['C', 3], ['C', 4]])
def test_hierarchy_operators_a(self) -> None: labels = ( (1, 1), (1, 2), (2, 1), (2, 2), ) ih1 = IndexHierarchy.from_labels(labels) self.assertEqual((ih1 * 2).tolist(), [[2, 2], [2, 4], [4, 2], [4, 4]]) self.assertEqual((-ih1).tolist(), [[-1, -1], [-1, -2], [-2, -1], [-2, -2]])
def test_hierarchy_copy_a(self): labels = ( ('I', 'A'), ('I', 'B'), ('II', 'A'), ('II', 'B'), ) ih1 = IndexHierarchy.from_labels(labels) ih2 = ih1.copy() self.assertEqual(ih2.values.tolist(), [['I', 'A'], ['I', 'B'], ['II', 'A'], ['II', 'B']])
def test_hierarchy_drop_level_a(self): labels = ( ('I', 'A', 1), ('I', 'B', 1), ('II', 'A', 1), ('II', 'B', 2), ) ih = IndexHierarchy.from_labels(labels) ih2 = ih.drop_level(-1) self.assertEqual(ih2.values.tolist(), [['I', 'A'], ['I', 'B'], ['II', 'A'], ['II', 'B']])