Repository: modin-project/modin

Issue:
series: is_monotonic function implementation



Discussion:

Resolving patch:
diff --git a/modin/backends/base/query_compiler.py b/modin/backends/base/query_compiler.py
--- a/modin/backends/base/query_compiler.py
+++ b/modin/backends/base/query_compiler.py
@@ -336,6 +336,26 @@ def reset_index(self, **kwargs):
     # we will implement a Distributed Series, and this will be returned
     # instead.
 
+    @abc.abstractmethod
+    def is_monotonic(self):
+        """Return boolean if values in the object are monotonic_increasing.
+
+        Returns
+        -------
+            bool
+        """
+        pass
+
+    @abc.abstractmethod
+    def is_monotonic_decreasing(self):
+        """Return boolean if values in the object are monotonic_decreasing.
+
+        Returns
+        -------
+            bool
+        """
+        pass
+
     @abc.abstractmethod
     def count(self, **kwargs):
         """Counts the number of non-NaN objects for each column or row.
diff --git a/modin/backends/pandas/query_compiler.py b/modin/backends/pandas/query_compiler.py
--- a/modin/backends/pandas/query_compiler.py
+++ b/modin/backends/pandas/query_compiler.py
@@ -440,6 +440,39 @@ def transpose(self, *args, **kwargs):
 
     # MapReduce operations
 
+    def _is_monotonic(self, type=None):
+        funcs = {
+            "increasing": lambda df: df.is_monotonic_increasing,
+            "decreasing": lambda df: df.is_monotonic_decreasing,
+        }
+
+        monotonic_fn = funcs.get(type, funcs["increasing"])
+
+        def is_monotonic_map(df):
+            df = df.squeeze()
+            return [monotonic_fn(df), df.iloc[0], df.iloc[len(df) - 1]]
+
+        def is_monotonic_reduce(df):
+            df = df.squeeze()
+
+            common_case = df[0].all()
+            left_edges = df[1]
+            right_edges = df[2]
+
+            edges_list = []
+            for i in range(len(left_edges)):
+                edges_list.extend([left_edges.iloc[i], right_edges.iloc[i]])
+
+            edge_case = monotonic_fn(pandas.Series(edges_list))
+            return [common_case and edge_case]
+
+        return MapReduceFunction.register(is_monotonic_map, is_monotonic_reduce)(self)
+
+    def is_monotonic_decreasing(self):
+        return self._is_monotonic(type="decreasing")
+
+    is_monotonic = _is_monotonic
+
     count = MapReduceFunction.register(pandas.DataFrame.count, pandas.DataFrame.sum)
     max = MapReduceFunction.register(pandas.DataFrame.max, pandas.DataFrame.max)
     min = MapReduceFunction.register(pandas.DataFrame.min, pandas.DataFrame.min)
diff --git a/modin/pandas/series.py b/modin/pandas/series.py
--- a/modin/pandas/series.py
+++ b/modin/pandas/series.py
@@ -1331,27 +1331,25 @@ def hasnans(self):
 
     @property
     def is_monotonic(self):
-        # We cannot default to pandas without a named function to call.
-        def is_monotonic(df):
-            return df.is_monotonic
+        """Return boolean if values in the object are monotonic_increasing.
 
-        return self._default_to_pandas(is_monotonic)
-
-    @property
-    def is_monotonic_decreasing(self):
-        # We cannot default to pandas without a named function to call.
-        def is_monotonic_decreasing(df):
-            return df.is_monotonic_decreasing
+        Returns
+        -------
+            bool
+        """
+        return self._reduce_dimension(self._query_compiler.is_monotonic())
 
-        return self._default_to_pandas(is_monotonic_decreasing)
+    is_monotonic_increasing = is_monotonic
 
     @property
-    def is_monotonic_increasing(self):
-        # We cannot default to pandas without a named function to call.
-        def is_monotonic_increasing(df):
-            return df.is_monotonic_increasing
+    def is_monotonic_decreasing(self):
+        """Return boolean if values in the object are monotonic_decreasing.
 
-        return self._default_to_pandas(is_monotonic_increasing)
+        Returns
+        -------
+            bool
+        """
+        return self._reduce_dimension(self._query_compiler.is_monotonic_decreasing())
 
     @property
     def is_unique(self):


Test patch:
diff --git a/modin/pandas/test/test_series.py b/modin/pandas/test/test_series.py
--- a/modin/pandas/test/test_series.py
+++ b/modin/pandas/test/test_series.py
@@ -1666,28 +1666,19 @@ def test_interpolate(data):
 @pytest.mark.parametrize("data", test_data_values, ids=test_data_keys)
 def test_is_monotonic(data):
     modin_series, pandas_series = create_test_series(data)
-    with pytest.warns(UserWarning):
-        assert modin_series.is_monotonic == pandas_series.is_monotonic
+    assert modin_series.is_monotonic == pandas_series.is_monotonic
 
 
 @pytest.mark.parametrize("data", test_data_values, ids=test_data_keys)
 def test_is_monotonic_decreasing(data):
     modin_series, pandas_series = create_test_series(data)
-    with pytest.warns(UserWarning):
-        assert (
-            modin_series.is_monotonic_decreasing
-            == pandas_series.is_monotonic_decreasing
-        )
+    assert modin_series.is_monotonic_decreasing == pandas_series.is_monotonic_decreasing
 
 
 @pytest.mark.parametrize("data", test_data_values, ids=test_data_keys)
 def test_is_monotonic_increasing(data):
     modin_series, pandas_series = create_test_series(data)
-    with pytest.warns(UserWarning):
-        assert (
-            modin_series.is_monotonic_increasing
-            == pandas_series.is_monotonic_increasing
-        )
+    assert modin_series.is_monotonic_increasing == pandas_series.is_monotonic_increasing
 
 
 @pytest.mark.parametrize("data", test_data_values, ids=test_data_keys)