Skip to content

Commit 092634e

Browse files
committed
mod/rmod
1 parent b0c2ba3 commit 092634e

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

python/pyspark/pandas/data_type_ops/boolean_ops.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import pandas as pd
2222
from pandas.api.types import CategoricalDtype
2323

24-
from pyspark.pandas.base import column_op, IndexOpsMixin
24+
from pyspark.pandas.base import column_op, IndexOpsMixin, numpy_column_op
2525
from pyspark.pandas._typing import Dtype, IndexOpsLike, SeriesOrIndex
2626
from pyspark.pandas.data_type_ops.base import (
2727
DataTypeOps,
@@ -35,6 +35,7 @@
3535
_is_boolean_type,
3636
)
3737
from pyspark.pandas.typedef.typehints import as_spark_type, extension_dtypes, pandas_on_spark_type
38+
from pyspark.pandas.utils import is_ansi_mode_enabled
3839
from pyspark.sql import functions as F, Column as PySparkColumn
3940
from pyspark.sql.types import BooleanType, StringType
4041
from pyspark.errors import PySparkValueError
@@ -136,13 +137,21 @@ def mod(self, left: IndexOpsLike, right: Any) -> SeriesOrIndex:
136137
raise TypeError(
137138
"Modulo can not be applied to %s and the given type." % self.pretty_name
138139
)
140+
spark_session = left._internal.spark_frame.sparkSession
141+
142+
def safe_mod(l: PySparkColumn, r: Any) -> PySparkColumn:
143+
if is_ansi_mode_enabled(spark_session):
144+
return F.when(F.lit(r == 0), F.lit(None)).otherwise(l % r)
145+
else:
146+
return l % r
147+
139148
if isinstance(right, numbers.Number):
140149
left = transform_boolean_operand_to_numeric(left, spark_type=as_spark_type(type(right)))
141-
return left % right
150+
return numpy_column_op(safe_mod)(left, right)
142151
else:
143152
assert isinstance(right, IndexOpsMixin)
144153
left = transform_boolean_operand_to_numeric(left, spark_type=right.spark.data_type)
145-
return left % right
154+
return numpy_column_op(safe_mod)(left, right)
146155

147156
def pow(self, left: IndexOpsLike, right: Any) -> SeriesOrIndex:
148157
_sanitize_list_like(right)
@@ -226,7 +235,17 @@ def rmod(self, left: IndexOpsLike, right: Any) -> SeriesOrIndex:
226235
_sanitize_list_like(right)
227236
if isinstance(right, numbers.Number) and not isinstance(right, bool):
228237
left = transform_boolean_operand_to_numeric(left, spark_type=as_spark_type(type(right)))
229-
return right % left
238+
spark_session = left._internal.spark_frame.sparkSession
239+
240+
def safe_rmod(left_col, right):
241+
if is_ansi_mode_enabled(spark_session):
242+
return F.when(left_col != 0, F.pmod(F.lit(right), left_col)).otherwise(
243+
F.lit(None)
244+
)
245+
else:
246+
return right % left
247+
248+
return numpy_column_op(safe_rmod)(left, right)
230249
else:
231250
raise TypeError(
232251
"Modulo can not be applied to %s and the given type." % self.pretty_name

python/pyspark/pandas/tests/data_type_ops/test_boolean_ops.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ def test_floordiv(self):
137137
for col in self.non_numeric_df_cols:
138138
self.assertRaises(TypeError, lambda: b_psser // psdf[col])
139139

140-
@unittest.skipIf(is_ansi_mode_test, ansi_mode_not_supported_message)
141140
def test_mod(self):
142141
pdf, psdf = self.pdf, self.psdf
143142

@@ -237,7 +236,6 @@ def test_rpow(self):
237236
self.assertRaises(TypeError, lambda: datetime.date(1994, 1, 1) ** b_psser)
238237
self.assertRaises(TypeError, lambda: datetime.datetime(1994, 1, 1) ** b_psser)
239238

240-
@unittest.skipIf(is_ansi_mode_test, ansi_mode_not_supported_message)
241239
def test_rmod(self):
242240
psdf = self.psdf
243241

@@ -248,6 +246,7 @@ def test_rmod(self):
248246
self.assert_eq(
249247
pd.Series([0.10000000000000009, 0.10000000000000009, None], dtype=float, name="bool"),
250248
0.1 % b_psser,
249+
check_exact=False, # [0.1, 0.1, nan] for pandas-on-Spark
251250
)
252251
self.assertRaises(TypeError, lambda: datetime.date(1994, 1, 1) % b_psser)
253252
self.assertRaises(TypeError, lambda: True % b_psser)

0 commit comments

Comments
 (0)