def _ufunc_binary_operator(self, *, operator: tp.Callable, other) -> np.ndarray: ''' Binary operators applied to an index always return an NP array. This deviates from Pandas, where some operations (multipling an int index by an int) result in a new Index, while other operations result in a np.array (using == on two Index). ''' if self._recache: self._update_array_cache() if issubclass(other.__class__, Index): other = other.values # operate on labels to labels if operator.__name__ == 'matmul': return matmul(self._labels, other) elif operator.__name__ == 'rmatmul': return matmul(other, self._labels) result = operator(self._labels, other) if not isinstance(result, np.ndarray): # see Series._ufunc_binary_operator for notes on why if isinstance(result, BOOL_TYPES): result = np.full(len(self._labels), result) else: raise RuntimeError( 'unexpected branch from non-array result of operator application to array' ) result.flags.writeable = False return result
def _ufunc_binary_operator(self, *, operator: UFunc, other: tp.Any) -> np.ndarray: ''' Binary operators applied to an index always return an NP array. This deviates from Pandas, where some operations (multipling an int index by an int) result in a new Index, while other operations result in a np.array (using == on two Index). ''' if self._recache: self._update_array_cache() values = self._labels other_is_array = False if issubclass(other.__class__, Index): other = other.values # operate on labels to labels other_is_array = True elif isinstance(other, np.ndarray): other_is_array = True if operator.__name__ == 'matmul': return matmul(values, other) elif operator.__name__ == 'rmatmul': return matmul(other, values) return apply_binary_operator( values=values, other=other, other_is_array=other_is_array, operator=operator, )
def test_matmul_g(self) -> None: # lhs: array 1D, rhs: array 1D, Series s1 = Series((3, 4, 2), index=('x', 'y', 'z')) self.assertEqual(matmul([10, 11, 12], s1.values), 98) self.assertEqual(matmul([10, 11, 12], s1), 98) with self.assertRaises(RuntimeError): self.assertEqual(matmul(s1, [10, 11]), 98)
def test_matmul_e(self) -> None: # lhs: series, rhs: series s1 = Series((3, 4, 2), index=('x', 'y', 'z')) s2 = Series((10, 11, 12), index=('x', 'y', 'z')) self.assertEqual(matmul(s1, s2), 98) self.assertEqual(matmul(s1, s2.values), 98)
def test_matmul_f(self) -> None: # lhs: array 1D, rhs: array 2D, Frame f1 = Frame.from_items((('a', (1, 2, 3)), ('b', (3, 4, 5))), index=('x', 'y', 'z')) self.assertEqual(matmul([3, 4, 5], f1.values).tolist(), [26, 50]) self.assertEqual( matmul([3, 4, 5], f1).to_pairs(), (('a', 26), ('b', 50)))
def test_matmul_d(self) -> None: # lhs: series, rhs: frame f1 = Frame.from_items((('a', (1, 2, 3)), ('b', (3, 4, 5))), index=('x', 'y', 'z')) s1 = Series((3, 4, 2), index=('x', 'y', 'z')) self.assertEqual(matmul(s1, f1).to_pairs(), (('a', 17), ('b', 35))) # produces a Series indexed 0, 1 self.assertEqual(matmul(s1, f1.values).to_pairs(), ((0, 17), (1, 35)))
def test_matmul_c(self) -> None: # lhs: frame, rhs: Series, 1D array f1 = Frame.from_items((('a', (1, 2, 3)), ('b', (3, 4, 5))), index=('x', 'y', 'z')) s1 = Series((10, 11), index=('a', 'b')) self.assertEqual( matmul(f1, s1).to_pairs(), (('x', 43), ('y', 64), ('z', 85))) self.assertEqual( matmul(f1, s1.values).to_pairs(), (('x', 43), ('y', 64), ('z', 85)))
def test_matmul_c(self) -> None: # lhs: frame, rhs: Series, 1D array f1 = Frame.from_items((('a', (1, 2, 3)), ('b', (3, 4, 5))), index=('x', 'y', 'z')) s1 = Series((10, 11), index=('a', 'b')) self.assertEqual( matmul(f1, s1).to_pairs(), (('x', 43), ('y', 64), ('z', 85))) self.assertEqual( matmul(f1, s1.values).to_pairs(), (('x', 43), ('y', 64), ('z', 85))) with self.assertRaises(RuntimeError): matmul(f1, np.arange(20).reshape(5, 4))
def test_matmul_j(self) -> None: f1 = Frame.from_dict(dict(a=(1, 2, 3), b=(5, 6, 7)), index=tuple('xyz'), name='foo') a1 = np.array([[5], [0]]) with self.assertRaises(RuntimeError): _ = matmul(a1, f1)
def test_matmul_a(self) -> None: # lhs: frame, rhs: array f1 = Frame.from_items((('a', (1, 2, 3)), ('b', (3, 4, 5))), index=('x', 'y', 'z')) self.assertEqual( matmul(f1, [4, 3]).to_pairs(), (('x', 13), ('y', 20), ('z', 27))) self.assertEqual( matmul(f1, np.array([4, 3])).to_pairs(), (('x', 13), ('y', 20), ('z', 27))) self.assertEqual( matmul(f1, [3, 4]).to_pairs(), (('x', 15), ('y', 22), ('z', 29))) self.assertEqual( matmul(f1, np.array([3, 4])).to_pairs(), (('x', 15), ('y', 22), ('z', 29)))
def _ufunc_binary_operator(self, *, operator: tp.Callable, other) -> np.ndarray: ''' Binary operators applied to an index always return an NP array. This deviates from Pandas, where some operations (multipling an int index by an int) result in a new Index, while other operations result in a np.array (using == on two Index). ''' if self._recache: self._update_array_cache() if issubclass(other.__class__, Index): other = other.values # operate on labels to labels if operator.__name__ == 'matmul': return matmul(self._labels, other) elif operator.__name__ == 'rmatmul': return matmul(other, self._labels) array = operator(self._labels, other) array.flags.writeable = False return array
def test_matmul_h(self) -> None: # lhs: array 2D, rhs: array 2D, Frame f1 = Frame.from_dict(dict(a=(1, 2, 3, 4), b=(5, 6, 7, 8)), index=tuple('wxyz')) f2 = Frame.from_dict(dict(p=(1, 2), q=(3, 4), r=(5, 6)), index=tuple('ab')) self.assertEqual( matmul(f1.values, f2).to_pairs(0), (('p', ((0, 11), (1, 14), (2, 17), (3, 20))), ('q', ((0, 23), (1, 30), (2, 37), (3, 44))), ('r', ((0, 35), (1, 46), (2, 57), (3, 68))))) self.assertEqual( matmul(f1, f2.values).to_pairs(0), ((0, (('w', 11), ('x', 14), ('y', 17), ('z', 20))), (1, (('w', 23), ('x', 30), ('y', 37), ('z', 44))), (2, (('w', 35), ('x', 46), ('y', 57), ('z', 68)))))
def test_matmul_b(self) -> None: # lhs: frame, rhs: array f1 = Frame.from_items((('a', (1, 2, 3)), ('b', (3, 4, 5))), index=('x', 'y', 'z')) # get an auto incremented integer columns self.assertEqual( matmul(f1, np.arange(10).reshape(2, 5)).to_pairs(0), ((0, (('x', 15), ('y', 20), ('z', 25))), (1, (('x', 19), ('y', 26), ('z', 33))), (2, (('x', 23), ('y', 32), ('z', 41))), (3, (('x', 27), ('y', 38), ('z', 49))), (4, (('x', 31), ('y', 44), ('z', 57)))))
def test_matmul_i(self) -> None: import itertools as it f1 = Frame.from_dict(dict(a=(1, 2), b=(5, 6)), index=tuple('yz')) f_container = lambda x: x f_values = lambda x: x.values for pair in ((f1, f1.T), (f1, f1.loc['y']), (f1['a'], f1), (f1.loc['y'], f1.loc['z'])): for x, y in it.combinations( (f_container, f_values, f_container, f_values), 2): post = matmul(x(pair[0]), y(pair[1])) # type: ignore if isinstance(post, (Series, Frame)): self.assertTrue(post.values.tolist(), (pair[0].values @ pair[1].values).tolist()) elif isinstance(post, np.ndarray): self.assertTrue(post.tolist(), (pair[0].values @ pair[1].values).tolist())
def test_matmul_g(self) -> None: # lhs: array 1D, rhs: array 1D, Series s1 = Series((3, 4, 2), index=('x', 'y', 'z')) self.assertEqual(matmul([10, 11, 12], s1.values), 98) self.assertEqual(matmul([10, 11, 12], s1), 98)