diff --git a/databricks/koalas/series.py b/databricks/koalas/series.py index 93b818d2f1..21ba0cd3c1 100644 --- a/databricks/koalas/series.py +++ b/databricks/koalas/series.py @@ -452,6 +452,10 @@ def spark_type(self): def add(self, other) -> "Series": return self + other + def __add__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__add__(self, other) + add.__doc__ = _flex_doc_SERIES.format( desc="Addition", op_name="+", @@ -463,6 +467,10 @@ def add(self, other) -> "Series": def radd(self, other) -> "Series": return other + self + def __radd__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__radd__(self, other) + radd.__doc__ = _flex_doc_SERIES.format( desc="Reverse Addition", op_name="+", @@ -498,6 +506,10 @@ def rdiv(self, other) -> "Series": def truediv(self, other) -> "Series": return self / other + def __truediv__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__truediv__(self, other) + truediv.__doc__ = _flex_doc_SERIES.format( desc="Floating division", op_name="/", @@ -509,6 +521,10 @@ def truediv(self, other) -> "Series": def rtruediv(self, other) -> "Series": return other / self + def __rtruediv__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__rtruediv__(self, other) + rtruediv.__doc__ = _flex_doc_SERIES.format( desc="Reverse Floating division", op_name="/", @@ -520,6 +536,10 @@ def rtruediv(self, other) -> "Series": def mul(self, other) -> "Series": return self * other + def __mul__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__mul__(self, other) + mul.__doc__ = _flex_doc_SERIES.format( desc="Multiplication", op_name="*", @@ -533,6 +553,10 @@ def mul(self, other) -> "Series": def rmul(self, other) -> "Series": return other * self + def __rmul__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__rmul__(self, other) + rmul.__doc__ = _flex_doc_SERIES.format( desc="Reverse Multiplication", op_name="*", @@ -544,6 +568,10 @@ def rmul(self, other) -> "Series": def sub(self, other) -> "Series": return self - other + def __sub__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__sub__(self, other) + sub.__doc__ = _flex_doc_SERIES.format( desc="Subtraction", op_name="-", @@ -557,6 +585,10 @@ def sub(self, other) -> "Series": def rsub(self, other) -> "Series": return other - self + def __rsub__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__rsub__(self, other) + rsub.__doc__ = _flex_doc_SERIES.format( desc="Reverse Subtraction", op_name="-", @@ -568,6 +600,10 @@ def rsub(self, other) -> "Series": def mod(self, other) -> "Series": return self % other + def __mod__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__mod__(self, other) + mod.__doc__ = _flex_doc_SERIES.format( desc="Modulo", op_name="%", @@ -579,6 +615,10 @@ def mod(self, other) -> "Series": def rmod(self, other) -> "Series": return other % self + def __rmod__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__rmod__(self, other) + rmod.__doc__ = _flex_doc_SERIES.format( desc="Reverse Modulo", op_name="%", @@ -590,6 +630,10 @@ def rmod(self, other) -> "Series": def pow(self, other) -> "Series": return self ** other + def __pow__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__pow__(self, other) + pow.__doc__ = _flex_doc_SERIES.format( desc="Exponential power of series", op_name="**", @@ -601,6 +645,10 @@ def pow(self, other) -> "Series": def rpow(self, other) -> "Series": return other ** self + def __rpow__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__rpow__(self, other) + rpow.__doc__ = _flex_doc_SERIES.format( desc="Reverse Exponential power", op_name="**", @@ -612,6 +660,10 @@ def rpow(self, other) -> "Series": def floordiv(self, other) -> "Series": return self // other + def __floordiv__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__floordiv__(self, other) + floordiv.__doc__ = _flex_doc_SERIES.format( desc="Integer division", op_name="//", @@ -623,6 +675,10 @@ def floordiv(self, other) -> "Series": def rfloordiv(self, other) -> "Series": return other // self + def __rfloordiv__(self, other): + other = ks.Index(other, name=self.name) if isinstance(other, (list, tuple)) else other + return IndexOpsMixin.__rfloordiv__(self, other) + rfloordiv.__doc__ = _flex_doc_SERIES.format( desc="Reverse Integer division", op_name="//", diff --git a/databricks/koalas/tests/test_ops_on_diff_frames.py b/databricks/koalas/tests/test_ops_on_diff_frames.py index 36eacc3d5a..65bd7636f7 100644 --- a/databricks/koalas/tests/test_ops_on_diff_frames.py +++ b/databricks/koalas/tests/test_ops_on_diff_frames.py @@ -1528,6 +1528,595 @@ def test_pow_and_rpow(self): self.assert_eq(pser ** pser_other, (kser ** kser_other).sort_index()) self.assert_eq(pser.rpow(pser_other), kser.rpow(kser_other).sort_index()) + def test_series_add_and_radd(self): + pser = pd.Series([1, 2, 3, 4, 5, 6], name="x") + kser = ks.from_pandas(pser) + + # other = Series + pandas_other = pd.Series( + [np.nan, 1, 3, 4, np.nan, 6], name="x", index=[10, 20, 30, 40, 50, 60] + ) + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.add(pandas_other), kser.add(koalas_other).sort_index()) + self.assert_eq(pser + pandas_other, (kser + koalas_other).sort_index()) + self.assert_eq(pser.radd(pandas_other), kser.radd(koalas_other).sort_index()) + + # other = Index + pandas_other = pd.Index([np.nan, 1, 3, 4, np.nan, 6], name="x") + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.add(pandas_other), kser.add(koalas_other).sort_index()) + self.assert_eq(pser + pandas_other, (kser + koalas_other).sort_index()) + self.assert_eq(pser.radd(pandas_other), kser.radd(koalas_other).sort_index()) + + # other = list + other = [np.nan, 1, 3, 4, np.nan, 6] + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.add(other), kser.add(other).sort_index()) + self.assert_eq(pser + other, (kser + other).sort_index()) + self.assert_eq(pser.radd(other), kser.radd(other).sort_index()) + self.assert_eq(other + pser, (other + kser).sort_index()) + else: + self.assert_eq(pser.add(other).rename("x"), kser.add(other).sort_index()) + self.assert_eq((pser + other).rename("x"), (kser + other).sort_index()) + self.assert_eq(pser.radd(other).rename("x"), kser.radd(other).sort_index()) + self.assert_eq((other + pser).rename("x"), (other + kser).sort_index()) + + # other = tuple + other = (np.nan, 1, 3, 4, np.nan, 6) + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.add(other), kser.add(other).sort_index()) + self.assert_eq(pser + other, (kser + other).sort_index()) + self.assert_eq(pser.radd(other), kser.radd(other).sort_index()) + self.assert_eq(other + pser, (other + kser).sort_index()) + else: + self.assert_eq(pser.add(other).rename("x"), kser.add(other).sort_index()) + self.assert_eq((pser + other).rename("x"), (kser + other).sort_index()) + self.assert_eq(pser.radd(other).rename("x"), kser.radd(other).sort_index()) + self.assert_eq((other + pser).rename("x"), (other + kser).sort_index()) + + # other = list with the different length + other = [np.nan, 1, 3, 4, np.nan] + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.add(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser + other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.radd(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other + kser + + # other = tuple with the different length + other = (np.nan, 1, 3, 4, np.nan) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.add(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser + other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.radd(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other + kser + + def test_series_sub_and_rsub(self): + pser = pd.Series([1, 2, 3, 4, 5, 6], name="x") + kser = ks.from_pandas(pser) + + # other = Series + pandas_other = pd.Series( + [np.nan, 1, 3, 4, np.nan, 6], name="x", index=[10, 20, 30, 40, 50, 60] + ) + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.sub(pandas_other), kser.sub(koalas_other).sort_index()) + self.assert_eq(pser - pandas_other, (kser - koalas_other).sort_index()) + self.assert_eq(pser.rsub(pandas_other), kser.rsub(koalas_other).sort_index()) + + # other = Index + pandas_other = pd.Index([np.nan, 1, 3, 4, np.nan, 6], name="x") + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.sub(pandas_other), kser.sub(koalas_other).sort_index()) + self.assert_eq(pser - pandas_other, (kser - koalas_other).sort_index()) + self.assert_eq(pser.rsub(pandas_other), kser.rsub(koalas_other).sort_index()) + + # other = list + other = [np.nan, 1, 3, 4, np.nan, 6] + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.sub(other), kser.sub(other).sort_index()) + self.assert_eq(pser - other, (kser - other).sort_index()) + # self.assert_eq(pser.rsub(other), kser.rsub(other).sort_index()) + # self.assert_eq(other - pser, (other - kser).sort_index()) + else: + self.assert_eq(pser.sub(other).rename("x"), kser.sub(other).sort_index()) + self.assert_eq((pser - other).rename("x"), (kser - other).sort_index()) + # self.assert_eq(pser.rsub(other).rename("x"), kser.rsub(other).sort_index()) + # self.assert_eq((other - pser).rename("x"), (other - kser).sort_index()) + + # other = tuple + other = (np.nan, 1, 3, 4, np.nan, 6) + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.sub(other), kser.sub(other).sort_index()) + self.assert_eq(pser - other, (kser - other).sort_index()) + # self.assert_eq(pser.rsub(other), kser.rsub(other).sort_index()) + # self.assert_eq(other - pser, (other - kser).sort_index()) + else: + self.assert_eq(pser.sub(other).rename("x"), kser.sub(other).sort_index()) + self.assert_eq((pser - other).rename("x"), (kser - other).sort_index()) + # self.assert_eq(pser.rsub(other).rename("x"), kser.rsub(other).sort_index()) + # self.assert_eq((other - pser).rename("x"), (other - kser).sort_index()) + + # other = list with the different length + other = [np.nan, 1, 3, 4, np.nan] + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.sub(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser - other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.rsub(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other - kser + + # other = tuple with the different length + other = (np.nan, 1, 3, 4, np.nan) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.sub(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser - other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.rsub(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other - kser + + def test_series_mul_and_rmul(self): + pser = pd.Series([1, 2, 3, 4, 5, 6], name="x") + kser = ks.from_pandas(pser) + + # other = Series + pandas_other = pd.Series( + [np.nan, 1, 3, 4, np.nan, 6], name="x", index=[10, 20, 30, 40, 50, 60] + ) + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.mul(pandas_other), kser.mul(koalas_other).sort_index()) + self.assert_eq(pser * pandas_other, (kser * koalas_other).sort_index()) + self.assert_eq(pser.rmul(pandas_other), kser.rmul(koalas_other).sort_index()) + + # other = Index + pandas_other = pd.Index([np.nan, 1, 3, 4, np.nan, 6], name="x") + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.mul(pandas_other), kser.mul(koalas_other).sort_index()) + self.assert_eq(pser * pandas_other, (kser * koalas_other).sort_index()) + self.assert_eq(pser.rmul(pandas_other), kser.rmul(koalas_other).sort_index()) + + # other = list + other = [np.nan, 1, 3, 4, np.nan, 6] + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.mul(other), kser.mul(other).sort_index()) + self.assert_eq(pser * other, (kser * other).sort_index()) + self.assert_eq(pser.rmul(other), kser.rmul(other).sort_index()) + self.assert_eq(other * pser, (other * kser).sort_index()) + else: + self.assert_eq(pser.mul(other).rename("x"), kser.mul(other).sort_index()) + self.assert_eq((pser * other).rename("x"), (kser * other).sort_index()) + self.assert_eq(pser.rmul(other).rename("x"), kser.rmul(other).sort_index()) + self.assert_eq((other * pser).rename("x"), (other * kser).sort_index()) + + # other = tuple + other = (np.nan, 1, 3, 4, np.nan, 6) + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.mul(other), kser.mul(other).sort_index()) + self.assert_eq(pser * other, (kser * other).sort_index()) + self.assert_eq(pser.rmul(other), kser.rmul(other).sort_index()) + self.assert_eq(other * pser, (other * kser).sort_index()) + else: + self.assert_eq(pser.mul(other).rename("x"), kser.mul(other).sort_index()) + self.assert_eq((pser * other).rename("x"), (kser * other).sort_index()) + self.assert_eq(pser.rmul(other).rename("x"), kser.rmul(other).sort_index()) + self.assert_eq((other * pser).rename("x"), (other * kser).sort_index()) + + # other = list with the different length + other = [np.nan, 1, 3, 4, np.nan] + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.mul(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser * other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.rmul(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other * kser + + # other = tuple with the different length + other = (np.nan, 1, 3, 4, np.nan) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.mul(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser * other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.rmul(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other * kser + + def test_series_pow_and_rpow(self): + pser = pd.Series([1, 2, 3, 4, 5, 6], name="x") + kser = ks.from_pandas(pser) + + # other = Series + pandas_other = pd.Series( + [np.nan, 1, 3, 4, np.nan, 6], name="x", index=[10, 20, 30, 40, 50, 60] + ) + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.pow(pandas_other), kser.pow(koalas_other).sort_index()) + self.assert_eq(pser ** pandas_other, (kser ** koalas_other).sort_index()) + self.assert_eq(pser.rpow(pandas_other), kser.rpow(koalas_other).sort_index()) + + # other = Index + pandas_other = pd.Index([np.nan, 1, 3, 4, np.nan, 6], name="x") + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.pow(pandas_other), kser.pow(koalas_other).sort_index()) + self.assert_eq(pser ** pandas_other, (kser ** koalas_other).sort_index()) + self.assert_eq(pser.rpow(pandas_other), kser.rpow(koalas_other).sort_index()) + + # other = list + other = [np.nan, 1, 3, 4, np.nan, 6] + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.pow(other), kser.pow(other).sort_index()) + self.assert_eq(pser ** other, (kser ** other).sort_index()) + self.assert_eq(pser.rpow(other), kser.rpow(other).sort_index()) + self.assert_eq(other ** pser, (other ** kser).sort_index()) + else: + self.assert_eq(pser.pow(other).rename("x"), kser.pow(other).sort_index()) + self.assert_eq((pser ** other).rename("x"), (kser ** other).sort_index()) + self.assert_eq(pser.rpow(other).rename("x"), kser.rpow(other).sort_index()) + self.assert_eq((other ** pser).rename("x"), (other ** kser).sort_index()) + + # other = tuple + other = (np.nan, 1, 3, 4, np.nan, 6) + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.pow(other), kser.pow(other).sort_index()) + self.assert_eq(pser ** other, (kser ** other).sort_index()) + self.assert_eq(pser.rpow(other), kser.rpow(other).sort_index()) + self.assert_eq(other ** pser, (other ** kser).sort_index()) + else: + self.assert_eq(pser.pow(other).rename("x"), kser.pow(other).sort_index()) + self.assert_eq((pser ** other).rename("x"), (kser ** other).sort_index()) + self.assert_eq(pser.rpow(other).rename("x"), kser.rpow(other).sort_index()) + self.assert_eq((other ** pser).rename("x"), (other ** kser).sort_index()) + + # other = list with the different length + other = [np.nan, 1, 3, 4, np.nan] + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.pow(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser ** other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.rpow(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other ** kser + + # other = tuple with the different length + other = (np.nan, 1, 3, 4, np.nan) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.pow(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser ** other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.rpow(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other ** kser + + def test_series_mod_and_rmod(self): + pser = pd.Series([1, 2, 3, 4, 5, 6], name="x") + kser = ks.from_pandas(pser) + + # other = Series + pandas_other = pd.Series( + [np.nan, 1, 3, 4, np.nan, 6], name="x", index=[10, 20, 30, 40, 50, 60] + ) + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.mod(pandas_other), kser.mod(koalas_other).sort_index()) + self.assert_eq(pser % pandas_other, (kser % koalas_other).sort_index()) + self.assert_eq(pser.rmod(pandas_other), kser.rmod(koalas_other).sort_index()) + + # other = Index + pandas_other = pd.Index([np.nan, 1, 3, 4, np.nan, 6], name="x") + koalas_other = ks.from_pandas(pandas_other) + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.mod(pandas_other), kser.mod(koalas_other).sort_index()) + self.assert_eq(pser % pandas_other, (kser % koalas_other).sort_index()) + self.assert_eq(pser.rmod(pandas_other), kser.rmod(koalas_other).sort_index()) + + # other = list + other = [np.nan, 1, 3, 4, np.nan, 6] + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.mod(other), kser.mod(other).sort_index()) + self.assert_eq(pser % other, (kser % other).sort_index()) + self.assert_eq(pser.rmod(other), kser.rmod(other).sort_index()) + self.assert_eq(other % pser, (other % kser).sort_index()) + else: + self.assert_eq(pser.mod(other).rename("x"), kser.mod(other).sort_index()) + self.assert_eq((pser % other).rename("x"), (kser % other).sort_index()) + self.assert_eq(pser.rmod(other).rename("x"), kser.rmod(other).sort_index()) + self.assert_eq((other % pser).rename("x"), (other % kser).sort_index()) + + # other = tuple + other = (np.nan, 1, 3, 4, np.nan, 6) + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.mod(other), kser.mod(other).sort_index()) + self.assert_eq(pser % other, (kser % other).sort_index()) + self.assert_eq(pser.rmod(other), kser.rmod(other).sort_index()) + self.assert_eq(other % pser, (other % kser).sort_index()) + else: + self.assert_eq(pser.mod(other).rename("x"), kser.mod(other).sort_index()) + self.assert_eq((pser % other).rename("x"), (kser % other).sort_index()) + self.assert_eq(pser.rmod(other).rename("x"), kser.rmod(other).sort_index()) + self.assert_eq((other % pser).rename("x"), (other % kser).sort_index()) + + # other = list with the different length + other = [np.nan, 1, 3, 4, np.nan] + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.mod(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser % other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.rmod(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other % kser + + # other = tuple with the different length + other = (np.nan, 1, 3, 4, np.nan) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.mod(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser % other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.rmod(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other % kser + + def test_series_div_and_rdiv(self): + pser = pd.Series([1, 2, 3, 4, 5, 6], name="x") + kser = ks.from_pandas(pser) + + # other = Series + pandas_other = pd.Series( + [np.nan, 1, 3, 4, np.nan, 6], name="x", index=[10, 20, 30, 40, 50, 60] + ) + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.div(pandas_other), kser.div(koalas_other).sort_index()) + self.assert_eq(pser / pandas_other, (kser / koalas_other).sort_index()) + self.assert_eq(pser.rdiv(pandas_other), kser.rdiv(koalas_other).sort_index()) + + # other = Index + pandas_other = pd.Index([np.nan, 1, 3, 4, np.nan, 6], name="x") + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.div(pandas_other), kser.div(koalas_other).sort_index()) + self.assert_eq(pser / pandas_other, (kser / koalas_other).sort_index()) + self.assert_eq(pser.rdiv(pandas_other), kser.rdiv(koalas_other).sort_index()) + + # other = list + other = [np.nan, 1, 3, 4, np.nan, 6] + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.div(other), kser.div(other).sort_index()) + self.assert_eq(pser / other, (kser / other).sort_index()) + self.assert_eq(pser.rdiv(other), kser.rdiv(other).sort_index()) + self.assert_eq(other / pser, (other / kser).sort_index()) + else: + self.assert_eq(pser.div(other).rename("x"), kser.div(other).sort_index()) + self.assert_eq((pser / other).rename("x"), (kser / other).sort_index()) + self.assert_eq(pser.rdiv(other).rename("x"), kser.rdiv(other).sort_index()) + self.assert_eq((other / pser).rename("x"), (other / kser).sort_index()) + + # other = tuple + other = (np.nan, 1, 3, 4, np.nan, 6) + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.div(other), kser.div(other).sort_index()) + self.assert_eq(pser / other, (kser / other).sort_index()) + self.assert_eq(pser.rdiv(other), kser.rdiv(other).sort_index()) + self.assert_eq(other / pser, (other / kser).sort_index()) + else: + self.assert_eq(pser.div(other).rename("x"), kser.div(other).sort_index()) + self.assert_eq((pser / other).rename("x"), (kser / other).sort_index()) + self.assert_eq(pser.rdiv(other).rename("x"), kser.rdiv(other).sort_index()) + self.assert_eq((other / pser).rename("x"), (other / kser).sort_index()) + + # other = list with the different length + other = [np.nan, 1, 3, 4, np.nan] + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.div(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser / other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.rdiv(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other / kser + + # other = tuple with the different length + other = (np.nan, 1, 3, 4, np.nan) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.div(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser / other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.rdiv(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other / kser + + def test_series_floordiv_and_rfloordiv(self): + pser = pd.Series([1, 2, 3, 4, 5, 6], name="x") + kser = ks.from_pandas(pser) + + # other = Series + pandas_other = pd.Series( + [np.nan, 1, 3, 4, np.nan, 6], name="x", index=[10, 20, 30, 40, 50, 60] + ) + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.floordiv(pandas_other), kser.floordiv(koalas_other).sort_index()) + self.assert_eq(pser // pandas_other, (kser // koalas_other).sort_index()) + self.assert_eq(pser.rfloordiv(pandas_other), kser.rfloordiv(koalas_other).sort_index()) + + # other = Index + pandas_other = pd.Index([np.nan, 1, 3, 4, np.nan, 6], name="x") + koalas_other = ks.from_pandas(pandas_other) + self.assert_eq(pser.floordiv(pandas_other), kser.floordiv(koalas_other).sort_index()) + self.assert_eq(pser // pandas_other, (kser // koalas_other).sort_index()) + self.assert_eq(pser.rfloordiv(pandas_other), kser.rfloordiv(koalas_other).sort_index()) + + # other = list + other = [np.nan, 1, 3, 4, np.nan, 6] + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.floordiv(other), kser.floordiv(other).sort_index()) + self.assert_eq(pser // other, (kser // other).sort_index()) + self.assert_eq(pser.rfloordiv(other), kser.rfloordiv(other).sort_index()) + self.assert_eq(other // pser, (other // kser).sort_index()) + else: + self.assert_eq(pser.floordiv(other).rename("x"), kser.floordiv(other).sort_index()) + self.assert_eq((pser // other).rename("x"), (kser // other).sort_index()) + self.assert_eq(pser.rfloordiv(other).rename("x"), kser.rfloordiv(other).sort_index()) + self.assert_eq((other // pser).rename("x"), (other // kser).sort_index()) + + # other = tuple + other = (np.nan, 1, 3, 4, np.nan, 6) + if LooseVersion(pd.__version__) >= LooseVersion("1.2"): + self.assert_eq(pser.floordiv(other), kser.floordiv(other).sort_index()) + self.assert_eq(pser // other, (kser // other).sort_index()) + self.assert_eq(pser.rfloordiv(other), kser.rfloordiv(other).sort_index()) + self.assert_eq(other // pser, (other // kser).sort_index()) + else: + self.assert_eq(pser.floordiv(other).rename("x"), kser.floordiv(other).sort_index()) + self.assert_eq((pser // other).rename("x"), (kser // other).sort_index()) + self.assert_eq(pser.rfloordiv(other).rename("x"), kser.rfloordiv(other).sort_index()) + self.assert_eq((other // pser).rename("x"), (other // kser).sort_index()) + + # other = list with the different length + other = [np.nan, 1, 3, 4, np.nan] + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.floordiv(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser // other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.rfloordiv(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other // kser + + # other = tuple with the different length + other = (np.nan, 1, 3, 4, np.nan) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.floordiv(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser // other + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + kser.rfloordiv(other) + with self.assertRaisesRegex( + ValueError, "operands could not be broadcast together with shapes" + ): + other // kser + class OpsOnDiffFramesDisabledTest(ReusedSQLTestCase, SQLTestUtils): @classmethod @@ -1694,3 +2283,91 @@ def test_pow_and_rpow(self): kser ** kser_other with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): kser.rpow(kser_other) + + def test_series_binary_operators(self): + pser = pd.Series([1, 2, 3, 4, 5, 6], name="x") + kser = ks.from_pandas(pser) + + others = ( + ks.Series([np.nan, 1, 3, 4, np.nan, 6], name="x"), + ks.Index([np.nan, 1, 3, 4, np.nan, 6], name="x"), + [np.nan, 1, 3, 4, np.nan, 6], + (np.nan, 1, 3, 4, np.nan, 6), + ) + # `add` and `radd` + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.add(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser + other + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.radd(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + other + kser + # `rub` and `rsub` + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.sub(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser - other + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.rsub(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + other - kser + # `mul` and `rmul` + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.mul(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser * other + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.rmul(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + other * kser + # `pow` and `rpow` + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.pow(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser ** other + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.rpow(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + other ** kser + # `mod` and `rmod` + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.mod(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser % other + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.rmod(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + other % kser + # `div` and `rdiv` + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.div(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser / other + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.rdiv(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + other / kser + # `floordiv` and `rfloordiv` + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.floordiv(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser // other + for other in others: + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + kser.rfloordiv(other) + with self.assertRaisesRegex(ValueError, "Cannot combine the series or dataframe"): + other // kser