Skip to content

Commit

Permalink
depr(python): Deprecate clip_min/clip_max in favor of clip (#11961
Browse files Browse the repository at this point in the history
)
  • Loading branch information
stinodego authored Oct 24, 2023
1 parent 3fbb34b commit 18cba0d
Show file tree
Hide file tree
Showing 5 changed files with 274 additions and 243 deletions.
171 changes: 80 additions & 91 deletions py-polars/polars/expr/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -7645,116 +7645,69 @@ def kurtosis(self, *, fisher: bool = True, bias: bool = True) -> Self:

def clip(
self,
lower_bound: NumericLiteral | TemporalLiteral | IntoExprColumn,
upper_bound: NumericLiteral | TemporalLiteral | IntoExprColumn,
lower_bound: NumericLiteral | TemporalLiteral | IntoExprColumn | None = None,
upper_bound: NumericLiteral | TemporalLiteral | IntoExprColumn | None = None,
) -> Self:
"""
Clip (limit) the values in an array to a `min` and `max` boundary.
Only works for physical numerical types.
If you want to clip other dtypes, consider writing a "when, then, otherwise"
expression. See :func:`when` for more information.
Set values outside the given boundaries to the boundary value.
Parameters
----------
lower_bound
Lower bound.
Lower bound. Accepts expression input.
Non-expression inputs are parsed as literals.
upper_bound
Upper bound.
Upper bound. Accepts expression input.
Non-expression inputs are parsed as literals.
Examples
See Also
--------
>>> df = pl.DataFrame({"foo": [-50, 5, None, 50]})
>>> df.with_columns(pl.col("foo").clip(1, 10).alias("foo_clipped"))
shape: (4, 2)
┌──────┬─────────────┐
│ foo ┆ foo_clipped │
│ --- ┆ --- │
│ i64 ┆ i64 │
╞══════╪═════════════╡
│ -50 ┆ 1 │
│ 5 ┆ 5 │
│ null ┆ null │
│ 50 ┆ 10 │
└──────┴─────────────┘
"""
lower_bound = parse_as_expression(lower_bound, str_as_lit=True)
upper_bound = parse_as_expression(upper_bound, str_as_lit=True)
return self._from_pyexpr(self._pyexpr.clip(lower_bound, upper_bound))
when
def clip_min(
self, lower_bound: NumericLiteral | TemporalLiteral | IntoExprColumn
) -> Self:
"""
Clip (limit) the values in an array to a `min` boundary.
Only works for physical numerical types.
If you want to clip other dtypes, consider writing a "when, then, otherwise"
expression. See :func:`when` for more information.
Parameters
----------
lower_bound
Lower bound.
Notes
-----
This method only works for numeric and temporal columns. To clip other data
types, consider writing a `when-then-otherwise` expression. See :func:`when`.
Examples
--------
>>> df = pl.DataFrame({"foo": [-50, 5, None, 50]})
>>> df.with_columns(pl.col("foo").clip_min(0).alias("foo_clipped"))
shape: (4, 2)
┌──────┬─────────────┐
│ foo ┆ foo_clipped │
│ --- ┆ --- │
│ i64 ┆ i64 │
╞══════╪═════════════╡
│ -50 ┆ 0 │
│ 5 ┆ 5 │
│ null ┆ null │
│ 50 ┆ 50 │
└──────┴─────────────┘
"""
lower_bound = parse_as_expression(lower_bound, str_as_lit=True)
return self._from_pyexpr(self._pyexpr.clip_min(lower_bound))
Specifying both a lower and upper bound:
def clip_max(
self, upper_bound: NumericLiteral | TemporalLiteral | IntoExprColumn
) -> Self:
"""
Clip (limit) the values in an array to a `max` boundary.
Only works for physical numerical types.
If you want to clip other dtypes, consider writing a "when, then, otherwise"
expression. See :func:`when` for more information.
>>> df = pl.DataFrame({"a": [-50, 5, 50, None]})
>>> df.with_columns(clip=pl.col("a").clip(1, 10))
shape: (4, 2)
┌──────┬──────┐
│ a ┆ clip │
│ --- ┆ --- │
│ i64 ┆ i64 │
╞══════╪══════╡
│ -50 ┆ 1 │
│ 5 ┆ 5 │
│ 50 ┆ 10 │
│ null ┆ null │
└──────┴──────┘
Parameters
----------
upper_bound
Upper bound.
Specifying only a single bound:
Examples
--------
>>> df = pl.DataFrame({"foo": [-50, 5, None, 50]})
>>> df.with_columns(pl.col("foo").clip_max(0).alias("foo_clipped"))
>>> df.with_columns(clip=pl.col("a").clip(upper_bound=10))
shape: (4, 2)
┌──────┬─────────────
foo ┆ foo_clipped
│ --- ┆ ---
│ i64 ┆ i64
╞══════╪═════════════
│ -50 ┆ -50
│ 5 ┆ 0
null ┆ null
50 ┆ 0
└──────┴─────────────
┌──────┬──────┐
a ┆ clip
│ --- ┆ --- │
│ i64 ┆ i64 │
╞══════╪══════╡
│ -50 ┆ -50 │
│ 5 ┆ 5
50 ┆ 10
null ┆ null
└──────┴──────┘
"""
upper_bound = parse_as_expression(upper_bound, str_as_lit=True)
return self._from_pyexpr(self._pyexpr.clip_max(upper_bound))
if lower_bound is not None:
lower_bound = parse_as_expression(lower_bound, str_as_lit=True)
if upper_bound is not None:
upper_bound = parse_as_expression(upper_bound, str_as_lit=True)
return self._from_pyexpr(self._pyexpr.clip(lower_bound, upper_bound))

def lower_bound(self) -> Self:
"""
Expand Down Expand Up @@ -9560,6 +9513,42 @@ def is_last(self) -> Self:
"""
return self.is_last_distinct()

@deprecate_function("Use `clip` instead.", version="0.19.12")
def clip_min(
self, lower_bound: NumericLiteral | TemporalLiteral | IntoExprColumn
) -> Self:
"""
Clip (limit) the values in an array to a `min` boundary.
.. deprecated:: 0.19.12
Use :func:`clip` instead.
Parameters
----------
lower_bound
Lower bound.
"""
return self.clip(lower_bound=lower_bound)

@deprecate_function("Use `clip` instead.", version="0.19.12")
def clip_max(
self, upper_bound: NumericLiteral | TemporalLiteral | IntoExprColumn
) -> Self:
"""
Clip (limit) the values in an array to a `max` boundary.
.. deprecated:: 0.19.12
Use :func:`clip` instead.
Parameters
----------
upper_bound
Upper bound.
"""
return self.clip(upper_bound=upper_bound)

def register_plugin(
self,
*,
Expand Down
121 changes: 71 additions & 50 deletions py-polars/polars/series/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
_time_to_pl_time,
)
from polars.utils.deprecation import (
deprecate_function,
deprecate_nonkeyword_arguments,
deprecate_renamed_function,
deprecate_renamed_parameter,
Expand Down Expand Up @@ -6166,72 +6167,58 @@ def kurtosis(self, *, fisher: bool = True, bias: bool = True) -> float | None:

def clip(
self,
lower_bound: NumericLiteral | TemporalLiteral | IntoExprColumn,
upper_bound: NumericLiteral | TemporalLiteral | IntoExprColumn,
lower_bound: NumericLiteral | TemporalLiteral | IntoExprColumn | None = None,
upper_bound: NumericLiteral | TemporalLiteral | IntoExprColumn | None = None,
) -> Series:
"""
Clip (limit) the values in an array to a `min` and `max` boundary.
Only works for physical numerical types.
If you want to clip other dtypes, consider writing a "when, then, otherwise"
expression. See :func:`when` for more information.
Set values outside the given boundaries to the boundary value.
Parameters
----------
lower_bound
Minimum value.
Lower bound. Accepts expression input.
Non-expression inputs are parsed as literals.
If set to ``None`` (default), no lower bound is applied.
upper_bound
Maximum value.
Upper bound. Accepts expression input.
Non-expression inputs are parsed as literals.
If set to ``None`` (default), no upper bound is applied.
See Also
--------
when
Notes
-----
This method only works for numeric and temporal columns. To clip other data
types, consider writing a `when-then-otherwise` expression. See :func:`when`.
Examples
--------
>>> s = pl.Series("foo", [-50, 5, None, 50])
Specifying both a lower and upper bound:
>>> s = pl.Series([-50, 5, 50, None])
>>> s.clip(1, 10)
shape: (4,)
Series: 'foo' [i64]
Series: '' [i64]
[
1
5
null
10
1
5
10
null
]
"""

def clip_min(
self, lower_bound: NumericLiteral | TemporalLiteral | IntoExprColumn
) -> Series:
"""
Clip (limit) the values in an array to a `min` boundary.
Only works for physical numerical types.
If you want to clip other dtypes, consider writing a "when, then, otherwise"
expression. See :func:`when` for more information.
Parameters
----------
lower_bound
Lower bound.
"""

def clip_max(
self, upper_bound: NumericLiteral | TemporalLiteral | IntoExprColumn
) -> Series:
"""
Clip (limit) the values in an array to a `max` boundary.
Only works for physical numerical types.
Specifying only a single bound:
If you want to clip other dtypes, consider writing a "when, then, otherwise"
expression. See :func:`when` for more information.
Parameters
----------
upper_bound
Upper bound.
>>> s.clip(upper_bound=10)
shape: (4,)
Series: '' [i64]
[
-50
5
10
null
]
"""

Expand Down Expand Up @@ -6848,6 +6835,40 @@ def is_last(self) -> Series:
"""

@deprecate_function("Use `clip` instead.", version="0.19.12")
def clip_min(
self, lower_bound: NumericLiteral | TemporalLiteral | IntoExprColumn
) -> Series:
"""
Clip (limit) the values in an array to a `min` boundary.
.. deprecated:: 0.19.12
Use :func:`clip` instead.
Parameters
----------
lower_bound
Lower bound.
"""

@deprecate_function("Use `clip` instead.", version="0.19.12")
def clip_max(
self, upper_bound: NumericLiteral | TemporalLiteral | IntoExprColumn
) -> Series:
"""
Clip (limit) the values in an array to a `max` boundary.
.. deprecated:: 0.19.12
Use :func:`clip` instead.
Parameters
----------
upper_bound
Upper bound.
"""

# Keep the `list` and `str` properties below at the end of the definition of Series,
# as to not confuse mypy with the type annotation `str` and `list`

Expand Down
19 changes: 9 additions & 10 deletions py-polars/src/expr/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,16 +462,15 @@ impl PyExpr {
self.inner.clone().ceil().into()
}

fn clip(&self, min: Self, max: Self) -> Self {
self.inner.clone().clip(min.inner, max.inner).into()
}

fn clip_min(&self, min: Self) -> Self {
self.inner.clone().clip_min(min.inner).into()
}

fn clip_max(&self, max: Self) -> Self {
self.inner.clone().clip_max(max.inner).into()
fn clip(&self, min: Option<Self>, max: Option<Self>) -> Self {
let expr = self.inner.clone();
let out = match (min, max) {
(Some(min), Some(max)) => expr.clip(min.inner, max.inner),
(Some(min), None) => expr.clip_min(min.inner),
(None, Some(max)) => expr.clip_max(max.inner),
(None, None) => expr,
};
out.into()
}

fn abs(&self) -> Self {
Expand Down
Loading

0 comments on commit 18cba0d

Please sign in to comment.