diff --git a/pandas/core/series.py b/pandas/core/series.py index 7d9303fa75acd..7c0c12c11e177 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1944,6 +1944,47 @@ def clip_lower(self, threshold): """ return pa.where(self < threshold, threshold, self) + def dot(self, other): + """ + Matrix multiplication with DataFrame or inner-product with Series objects + + Parameters + ---------- + other : Series or DataFrame + + Returns + ------- + dot_product : scalar or Series + """ + from pandas.core.frame import DataFrame + if isinstance(other, (Series, DataFrame)): + common = self.index.union(other.index) + if (len(common) > len(self.index) or + len(common) > len(other.index)): + raise ValueError('matrices are not aligned') + + left = self.reindex(index=common, copy=False) + right = other.reindex(index=common, copy=False) + lvals = left.values + rvals = right.values + else: + left = self + lvals = self.values + rvals = np.asarray(other) + if lvals.shape[0] != rvals.shape[0]: + raise Exception('Dot product shape mismatch, %s vs %s' % + (lvals.shape, rvals.shape)) + + if isinstance(other, DataFrame): + return self._constructor(np.dot(lvals, rvals), + index=other.columns) + elif isinstance(other, Series): + return np.dot(lvals, rvals) + elif isinstance(rvals, np.ndarray): + return np.dot(lvals, rvals) + else: # pragma: no cover + raise TypeError('unsupported type: %s' % type(other)) + #------------------------------------------------------------------------------ # Combination diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index 20ff6e95b436c..4845ae5258892 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -2486,6 +2486,33 @@ def test_count(self): self.assertEqual(self.ts.count(), np.isfinite(self.ts).sum()) + def test_dot(self): + a = Series(np.random.randn(4), index=['p', 'q', 'r', 's']) + b = DataFrame(np.random.randn(3, 4), index=['1', '2', '3'], + columns=['p', 'q', 'r', 's']).T + + result = a.dot(b) + expected = Series(np.dot(a.values, b.values), + index=['1', '2', '3']) + assert_series_equal(result, expected) + + #Check index alignment + b2 = b.reindex(index=reversed(b.index)) + result = a.dot(b) + assert_series_equal(result, expected) + + # Check ndarray argument + result = a.dot(b.values) + self.assertTrue(np.all(result == expected.values)) + self.assertEquals(a.dot(b['2'].values), expected['2']) + + #Check series argument + self.assertEquals(a.dot(b['1']), expected['1']) + self.assertEquals(a.dot(b2['1']), expected['1']) + + self.assertRaises(Exception, a.dot, a.values[:3]) + self.assertRaises(ValueError, a.dot, b.T) + def test_value_counts_nunique(self): s = Series(['a', 'b', 'b', 'b', 'b', 'a', 'c', 'd', 'd', 'a']) hist = s.value_counts()