Skip to content

Commit

Permalink
[SNOW-1458134]: Add support for monotonic checks for Series and Index
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-rdurrani committed Aug 28, 2024
1 parent 639724b commit b3770cb
Show file tree
Hide file tree
Showing 10 changed files with 415 additions and 58 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@
- Added support for `Index.is_boolean`, `Index.is_integer`, `Index.is_floating`, `Index.is_numeric`, and `Index.is_object`.
- Added support for `DatetimeIndex.round`, `DatetimeIndex.floor` and `DatetimeIndex.ceil`.
- Added support for `Series.dt.days_in_month` and `Series.dt.daysinmonth`.
- Added support for `Series.is_monotonic_increasing` and `Series.is_monotonic_decreasing`.
- Added support for `Index.is_monotonic_increasing` and `Index.is_monotonic_decreasing`.

#### Improvements

Expand Down
4 changes: 2 additions & 2 deletions docs/source/modin/supported/index_supported.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ Attributes
+-----------------------------+---------------------------------+----------------------------------------------------+
| ``values`` | Y | |
+-----------------------------+---------------------------------+----------------------------------------------------+
| ``is_monotonic_increasing`` | N | |
| ``is_monotonic_increasing`` | Y | |
+-----------------------------+---------------------------------+----------------------------------------------------+
| ``is_monotonic_decreasing`` | N | |
| ``is_monotonic_decreasing`` | Y | |
+-----------------------------+---------------------------------+----------------------------------------------------+
| ``is_unique`` | Y | |
+-----------------------------+---------------------------------+----------------------------------------------------+
Expand Down
4 changes: 2 additions & 2 deletions docs/source/modin/supported/series_supported.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ Attributes
+-----------------------------+---------------------------------+----------------------------------------------------+
| ``index`` | Y | |
+-----------------------------+---------------------------------+----------------------------------------------------+
| ``is_monotonic_decreasing`` | N | |
| ``is_monotonic_decreasing`` | Y | |
+-----------------------------+---------------------------------+----------------------------------------------------+
| ``is_monotonic_increasing`` | N | |
| ``is_monotonic_increasing`` | Y | |
+-----------------------------+---------------------------------+----------------------------------------------------+
| ``is_unique`` | Y | |
+-----------------------------+---------------------------------+----------------------------------------------------+
Expand Down
16 changes: 0 additions & 16 deletions src/snowflake/snowpark/modin/pandas/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -2481,22 +2481,6 @@ def isnull(self):
"""
return super().isnull()

@property
def is_monotonic_increasing(self): # noqa: RT01, D200
"""
Return True if values in the Series are monotonic_increasing.
"""
# TODO: SNOW-1063347: Modin upgrade - modin.pandas.Series functions
return self._reduce_dimension(self._query_compiler.is_monotonic_increasing())

@property
def is_monotonic_decreasing(self): # noqa: RT01, D200
"""
Return True if values in the Series are monotonic_decreasing.
"""
# TODO: SNOW-1063347: Modin upgrade - modin.pandas.Series functions
return self._reduce_dimension(self._query_compiler.is_monotonic_decreasing())

@property
def is_unique(self): # noqa: RT01, D200
"""
Expand Down
151 changes: 129 additions & 22 deletions src/snowflake/snowpark/modin/plugin/compiler/snowflake_query_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2272,9 +2272,105 @@ def reindex(
else:
return self._reindex_axis_1(labels=labels, **kwargs)

def is_monotonic_decreasing(self, index: bool) -> "SnowflakeQueryCompiler":
"""
Returns a QueryCompiler containing only a column that checks for monotonically
decreasing values.

Parameters
----------
index: bool
Whether or not this is called by an `Index` object. If False, it is assumed
that this method is called by a `Series` object, and monotonicity is checked
for the first data column. If True, monotonicity is checked for the first index
column.

Returns
-------
SnowflakeQueryCompiler
QueryCompiler with column to ascertain whether data is monotonically decreasing.
"""
col_to_check = (
self._modin_frame.index_column_snowflake_quoted_identifiers[0]
if index
else self._modin_frame.data_column_snowflake_quoted_identifiers[0]
)
(
new_qc,
_,
monotonic_decreasing_snowflake_quoted_identifier,
) = self._add_columns_for_monotonicity_checks(
col_to_check=col_to_check, columns_to_add="decreasing"
)
new_modin_frame = new_qc._modin_frame
return SnowflakeQueryCompiler(
InternalFrame.create(
ordered_dataframe=new_modin_frame.ordered_dataframe.limit(
n=1, sort=False
),
data_column_pandas_index_names=new_modin_frame.data_column_pandas_index_names,
data_column_pandas_labels=["monotonic_column"],
data_column_snowflake_quoted_identifiers=[
monotonic_decreasing_snowflake_quoted_identifier
],
index_column_pandas_labels=new_modin_frame.index_column_pandas_labels,
index_column_snowflake_quoted_identifiers=new_modin_frame.index_column_snowflake_quoted_identifiers,
data_column_types=None,
index_column_types=None,
)
)

def is_monotonic_increasing(self, index: bool) -> "SnowflakeQueryCompiler":
"""
Returns a QueryCompiler containing only a column that checks for monotonically
increasing values.

Parameters
----------
index: bool
Whether or not this is called by an `Index` object. If False, it is assumed
that this method is called by a `Series` object, and monotonicity is checked
for the first data column. If True, monotonicity is checked for the first index
column.

Returns
-------
SnowflakeQueryCompiler
QueryCompiler with column to ascertain whether data is monotonically increasing.
"""
col_to_check = (
self._modin_frame.index_column_snowflake_quoted_identifiers[0]
if index
else self._modin_frame.data_column_snowflake_quoted_identifiers[0]
)
(
new_qc,
monotonic_increasing_snowflake_quoted_identifier,
_,
) = self._add_columns_for_monotonicity_checks(
col_to_check=col_to_check, columns_to_add="increasing"
)
new_modin_frame = new_qc._modin_frame
return SnowflakeQueryCompiler(
InternalFrame.create(
ordered_dataframe=new_modin_frame.ordered_dataframe.limit(
n=1, sort=False
),
data_column_pandas_index_names=new_modin_frame.data_column_pandas_index_names,
data_column_pandas_labels=["monotonic_column"],
data_column_snowflake_quoted_identifiers=[
monotonic_increasing_snowflake_quoted_identifier
],
index_column_pandas_labels=new_modin_frame.index_column_pandas_labels,
index_column_snowflake_quoted_identifiers=new_modin_frame.index_column_snowflake_quoted_identifiers,
data_column_types=None,
index_column_types=None,
)
)

def _add_columns_for_monotonicity_checks(
self, col_to_check: str
) -> tuple["SnowflakeQueryCompiler", str, str]:
self, col_to_check: str, columns_to_add: Optional[str] = None
) -> tuple["SnowflakeQueryCompiler", Optional[str], Optional[str]]:
"""
Adds columns that check for monotonicity (increasing or decreasing) in the
specified column.
Expand All @@ -2283,6 +2379,8 @@ def _add_columns_for_monotonicity_checks(
----------
col_to_check : str
The Snowflake quoted identifier for the column whose monotonicity to check.
columns_to_add : str, optional
Whether or not to add all columns, and if not, which columns to add.

Returns
-------
Expand All @@ -2293,36 +2391,45 @@ def _add_columns_for_monotonicity_checks(
"""
self._raise_not_implemented_error_for_timedelta()

assert columns_to_add in [
None,
"increasing",
"decreasing",
], "Invalid value passed to function"
modin_frame = self._modin_frame
modin_frame = modin_frame.ensure_row_position_column()
row_position_column = modin_frame.row_position_snowflake_quoted_identifier
monotonic_decreasing_snowflake_quoted_id = None
monotonic_increasing_snowflake_quoted_id = None
modin_frame = modin_frame.append_column(
"_index_lag_col",
lag(col_to_check).over(Window.order_by(row_position_column)),
)
lag_col_snowflake_quoted_id = (
modin_frame.data_column_snowflake_quoted_identifiers[-1]
)
modin_frame = modin_frame.append_column(
"_is_monotonic_decreasing",
coalesce(
min_(col(col_to_check) < col(lag_col_snowflake_quoted_id)).over(),
pandas_lit(False),
),
)
monotonic_decreasing_snowflake_quoted_id = (
modin_frame.data_column_snowflake_quoted_identifiers[-1]
)
modin_frame = modin_frame.append_column(
"_is_monotonic_increasing",
coalesce(
min_(col(col_to_check) > col(lag_col_snowflake_quoted_id)).over(),
pandas_lit(False),
),
)
monotonic_increasing_snowflake_quoted_id = (
modin_frame.data_column_snowflake_quoted_identifiers[-1]
)
if columns_to_add in [None, "decreasing"]:
modin_frame = modin_frame.append_column(
"_is_monotonic_decreasing",
coalesce(
min_(col(col_to_check) <= col(lag_col_snowflake_quoted_id)).over(),
pandas_lit(False),
),
)
monotonic_decreasing_snowflake_quoted_id = (
modin_frame.data_column_snowflake_quoted_identifiers[-1]
)
if columns_to_add in [None, "increasing"]:
modin_frame = modin_frame.append_column(
"_is_monotonic_increasing",
coalesce(
min_(col(col_to_check) >= col(lag_col_snowflake_quoted_id)).over(),
pandas_lit(False),
),
)
monotonic_increasing_snowflake_quoted_id = (
modin_frame.data_column_snowflake_quoted_identifiers[-1]
)
data_column_pandas_labels = modin_frame.data_column_pandas_labels
data_column_snowflake_quoted_identifiers = (
modin_frame.data_column_snowflake_quoted_identifiers
Expand Down
44 changes: 32 additions & 12 deletions src/snowflake/snowpark/modin/plugin/docstrings/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -3659,6 +3659,38 @@ def hasnans():
Return True if there are any NaNs.
"""

@property
def is_monotonic_increasing():
"""
Return boolean if values in the object are monotonically decreasing.
Examples
--------
>>> s = pd.Series([3, 2, 2, 1])
>>> s.is_monotonic_decreasing
True
>>> s = pd.Series([1, 2, 3])
>>> s.is_monotonic_decreasing
False
"""

@property
def is_monotonic_decreasing():
"""
Return boolean if values in the object are monotonically increasing.
Examples
--------
>>> s = pd.Series([1, 2, 2])
>>> s.is_monotonic_increasing
True
>>> s = pd.Series([3, 2, 1])
>>> s.is_monotonic_increasing
False
"""

def isna():
"""
Detect missing values.
Expand Down Expand Up @@ -3719,18 +3751,6 @@ def isnull():
dtype: bool
"""

@property
def is_monotonic_increasing():
"""
Return True if values in the Series are monotonic_increasing.
"""

@property
def is_monotonic_decreasing():
"""
Return True if values in the Series are monotonic_decreasing.
"""

@property
def is_unique():
"""
Expand Down
32 changes: 28 additions & 4 deletions src/snowflake/snowpark/modin/plugin/extensions/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,6 @@ def values(self) -> ArrayLike:
return self.to_pandas().values

@property
@index_not_implemented()
def is_monotonic_increasing(self) -> None:
"""
Return a boolean if the values are equal or increasing.
Expand All @@ -411,11 +410,23 @@ def is_monotonic_increasing(self) -> None:
See Also
--------
Index.is_monotonic_decreasing : Check if the values are equal or decreasing
Examples
--------
>>> pd.Index([1, 2, 3]).is_monotonic_increasing
True
>>> pd.Index([1, 2, 2]).is_monotonic_increasing
True
>>> pd.Index([1, 3, 2]).is_monotonic_increasing
False
"""
# TODO: SNOW-1458134 implement is_monotonic_increasing
return (
self._query_compiler.is_monotonic_increasing(index=True)
.to_pandas()
.squeeze()
)

@property
@index_not_implemented()
def is_monotonic_decreasing(self) -> None:
"""
Return a boolean if the values are equal or decreasing.
Expand All @@ -428,8 +439,21 @@ def is_monotonic_decreasing(self) -> None:
See Also
--------
Index.is_monotonic_increasing : Check if the values are equal or increasing
Examples
--------
>>> pd.Index([3, 2, 1]).is_monotonic_decreasing
True
>>> pd.Index([3, 2, 2]).is_monotonic_decreasing
True
>>> pd.Index([3, 1, 2]).is_monotonic_decreasing
False
"""
# TODO: SNOW-1458134 implement is_monotonic_decreasing
return (
self._query_compiler.is_monotonic_decreasing(index=True)
.to_pandas()
.squeeze()
)

@property
def is_unique(self) -> bool:
Expand Down
26 changes: 26 additions & 0 deletions src/snowflake/snowpark/modin/plugin/extensions/series_overrides.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,29 @@ def plot(
@series_not_implemented()
def transform(self, func, axis=0, *args, **kwargs): # noqa: PR01, RT01, D200
pass # pragma: no cover


@register_series_accessor("is_monotonic_increasing")
@property
@snowpark_pandas_telemetry_method_decorator
def is_monotonic_increasing(self): # noqa: RT01, D200
"""
Return True if values in the Series are monotonic_increasing.
"""
# TODO: SNOW-1063347: Modin upgrade - modin.pandas.Series functions
return self._reduce_dimension(
self._query_compiler.is_monotonic_increasing(index=False)
)


@register_series_accessor("is_monotonic_decreasing")
@property
@snowpark_pandas_telemetry_method_decorator
def is_monotonic_decreasing(self): # noqa: RT01, D200
"""
Return True if values in the Series are monotonic_decreasing.
"""
# TODO: SNOW-1063347: Modin upgrade - modin.pandas.Series functions
return self._reduce_dimension(
self._query_compiler.is_monotonic_decreasing(index=False)
)
Loading

0 comments on commit b3770cb

Please sign in to comment.