python – How to increase values ​​of polars dataframe column by index

Let me see if we can build on @ritchie46 response and nudge you closer to the finish line.

Data

I’ve concatenated the ‘open’, ‘high’, and ‘low’ columns in your sample data, just to give us some data to work with. I’ve also added a row_nr column, just for discussion. (It won’t be used in any calculations whatsoever, so you don’t need to include it in your final code.)

import numpy as np
import polars as pl
from scipy.signal import argrelextrema

df = pl.DataFrame(
    {
        "col1": [
            46405.49, 46407.36, 46005.43, 46174.00, 30171.32, 30457.01, 30397.12, 30373.53,
            47444.11, 46461.14, 46293.38, 46287.97, 30670.51, 30616.18, 30625.98, 30529.90,
            46248.84, 45744.77, 45834.39, 45787.00, 30101.07, 30281.89, 29967.07, 30042.09,
        ]
    }
).with_row_count()
df
shape: (24, 2)
┌────────┬──────────┐
│ row_nr ┆ col1     │
│ ---    ┆ ---      │
│ u32    ┆ f64      │
╞════════╪══════════╡
│ 0      ┆ 46405.49 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 1      ┆ 46407.36 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 2      ┆ 46005.43 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 3      ┆ 46174.0  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 4      ┆ 30171.32 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 5      ┆ 30457.01 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 6      ┆ 30397.12 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 7      ┆ 30373.53 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 8      ┆ 47444.11 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 9      ┆ 46461.14 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 10     ┆ 46293.38 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 11     ┆ 46287.97 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 12     ┆ 30670.51 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 13     ┆ 30616.18 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 14     ┆ 30625.98 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 15     ┆ 30529.9  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 16     ┆ 46248.84 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 17     ┆ 45744.77 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 18     ┆ 45834.39 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 19     ┆ 45787.0  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 20     ┆ 30101.07 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 21     ┆ 30281.89 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 22     ┆ 29967.07 │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 23     ┆ 30042.09 │
└────────┴──────────┘

Now, let’s run the scipy.signal.argrelextrema code on this data.

for _order in range(1, 7):
    print(
        "order:", _order, ":", argrelextrema(df["col1"].to_numpy(), np.less, order=_order)
    )
order: 1 : (array([ 2,  4,  7, 13, 15, 17, 20, 22]),)
order: 2 : (array([ 4,  7, 15, 22]),)
order: 3 : (array([ 4, 15, 22]),)
order: 4 : (array([ 4, 15, 22]),)
order: 5 : (array([ 4, 22]),)
order: 6 : (array([ 4, 22]),)

From the output, it looks like you’re trying to find the index of any row that is the minimum value of a window centered on that row, for various window sizes.

For example, row_nr 2 is a local minimum of a window of size 3, centered on row_nr 2. (Here, order=1 in the call to argrelextrema means “including one value above and below”, and hence “window size” = (order * 2) + 1) = 3.

Let’s replicate this in Polars. We’ll take it in steps.

rolling_min

First, let’s use the rolling_min expression to calculate rolling minimums corresponding to order from 1 to 6. Notice that Polars allows us to generate a list of expressions outside of the with_columns context. (This often helps keep code more readable.)

I’m converting the scipy order keyword to the equivalent window_size for rolling_min. Also, I’m setting the min_periods to make sure that there is at least one value on each side of the center value of any window (to replicate the scipy calculations).

expr_list = [
        pl.col("col1").rolling_min(
            window_size=_order * 2 + 1,
            min_periods=_order + 2,
            center=True
        ).alias("roll_min" + str(_order))
    for _order in range(1, 7)
]
df.with_columns(expr_list)
shape: (24, 8)
┌────────┬──────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┐
│ row_nr ┆ col1     ┆ roll_min1 ┆ roll_min2 ┆ roll_min3 ┆ roll_min4 ┆ roll_min5 ┆ roll_min6 │
│ ---    ┆ ---      ┆ ---       ┆ ---       ┆ ---       ┆ ---       ┆ ---       ┆ ---       │
│ u32    ┆ f64      ┆ f64       ┆ f64       ┆ f64       ┆ f64       ┆ f64       ┆ f64       │
╞════════╪══════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡
│ 0      ┆ 46405.49 ┆ null      ┆ null      ┆ null      ┆ null      ┆ null      ┆ null      │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 1      ┆ 46407.36 ┆ 46005.43  ┆ 46005.43  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 2      ┆ 46005.43 ┆ 46005.43  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 3      ┆ 46174.0  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 4      ┆ 30171.32 ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 5      ┆ 30457.01 ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 6      ┆ 30397.12 ┆ 30373.53  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 7      ┆ 30373.53 ┆ 30373.53  ┆ 30373.53  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 8      ┆ 47444.11 ┆ 30373.53  ┆ 30373.53  ┆ 30373.53  ┆ 30171.32  ┆ 30171.32  ┆ 30171.32  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 9      ┆ 46461.14 ┆ 46293.38  ┆ 30373.53  ┆ 30373.53  ┆ 30373.53  ┆ 30171.32  ┆ 30171.32  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 10     ┆ 46293.38 ┆ 46287.97  ┆ 30670.51  ┆ 30373.53  ┆ 30373.53  ┆ 30373.53  ┆ 30171.32  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 11     ┆ 46287.97 ┆ 30670.51  ┆ 30616.18  ┆ 30616.18  ┆ 30373.53  ┆ 30373.53  ┆ 30373.53  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 12     ┆ 30670.51 ┆ 30616.18  ┆ 30616.18  ┆ 30529.9   ┆ 30529.9   ┆ 30373.53  ┆ 30373.53  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 13     ┆ 30616.18 ┆ 30616.18  ┆ 30529.9   ┆ 30529.9   ┆ 30529.9   ┆ 30529.9   ┆ 30373.53  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 14     ┆ 30625.98 ┆ 30529.9   ┆ 30529.9   ┆ 30529.9   ┆ 30529.9   ┆ 30529.9   ┆ 30101.07  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 15     ┆ 30529.9  ┆ 30529.9   ┆ 30529.9   ┆ 30529.9   ┆ 30529.9   ┆ 30101.07  ┆ 30101.07  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 16     ┆ 46248.84 ┆ 30529.9   ┆ 30529.9   ┆ 30529.9   ┆ 30101.07  ┆ 30101.07  ┆ 29967.07  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 17     ┆ 45744.77 ┆ 45744.77  ┆ 30529.9   ┆ 30101.07  ┆ 30101.07  ┆ 29967.07  ┆ 29967.07  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 18     ┆ 45834.39 ┆ 45744.77  ┆ 30101.07  ┆ 30101.07  ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 19     ┆ 45787.0  ┆ 30101.07  ┆ 30101.07  ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 20     ┆ 30101.07 ┆ 30101.07  ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 21     ┆ 30281.89 ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 22     ┆ 29967.07 ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  ┆ 29967.07  │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 23     ┆ 30042.09 ┆ null      ┆ null      ┆ null      ┆ null      ┆ null      ┆ null      │
└────────┴──────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┘

Looking at the output in roll_min_1 (the equivalent of an order=1 call for argrelextrema), we see that the values ​​in roll_min_1 equal the values ​​in col1 for row_nr 2, 4, 7, 13, 15, 17, 20, 22 … which corresponds exactly to the output of argrelextrema for order=1. Likewise, for the other roll_min_X columns. We’ll use this fact in the next step.

Obtaining the row index

As @ritchie46 points out, in Polars, we use conditions (not indexing). We’ll modify the above code to identify whether the value in col1 equals it’s rolling min, for each of our window sizes.

expr_list = [
    (
        pl.col("col1").rolling_min(
            window_size=_order * 2 + 1,
            min_periods=_order + 2,
            center=True
        )
        == pl.col("col1")
    ).alias("min_idx_" + str(_order))
    for _order in range(1, 7)
]
df.with_columns(expr_list)
shape: (24, 8)
┌────────┬──────────┬───────────┬───────────┬───────────┬───────────┬───────────┬───────────┐
│ row_nr ┆ col1     ┆ min_idx_1 ┆ min_idx_2 ┆ min_idx_3 ┆ min_idx_4 ┆ min_idx_5 ┆ min_idx_6 │
│ ---    ┆ ---      ┆ ---       ┆ ---       ┆ ---       ┆ ---       ┆ ---       ┆ ---       │
│ u32    ┆ f64      ┆ bool      ┆ bool      ┆ bool      ┆ bool      ┆ bool      ┆ bool      │
╞════════╪══════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡
│ 0      ┆ 46405.49 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 1      ┆ 46407.36 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 2      ┆ 46005.43 ┆ true      ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 3      ┆ 46174.0  ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 4      ┆ 30171.32 ┆ true      ┆ true      ┆ true      ┆ true      ┆ true      ┆ true      │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 5      ┆ 30457.01 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 6      ┆ 30397.12 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 7      ┆ 30373.53 ┆ true      ┆ true      ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 8      ┆ 47444.11 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 9      ┆ 46461.14 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 10     ┆ 46293.38 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 11     ┆ 46287.97 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 12     ┆ 30670.51 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 13     ┆ 30616.18 ┆ true      ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 14     ┆ 30625.98 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 15     ┆ 30529.9  ┆ true      ┆ true      ┆ true      ┆ true      ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 16     ┆ 46248.84 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 17     ┆ 45744.77 ┆ true      ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 18     ┆ 45834.39 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 19     ┆ 45787.0  ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 20     ┆ 30101.07 ┆ true      ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 21     ┆ 30281.89 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 22     ┆ 29967.07 ┆ true      ┆ true      ┆ true      ┆ true      ┆ true      ┆ true      │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 23     ┆ 30042.09 ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     ┆ false     │
└────────┴──────────┴───────────┴───────────┴───────────┴───────────┴───────────┴───────────┘

Notice that for min_idx_1the values ​​are true for row_nr 2, 4, 7, 13, 15, 17, 20, 22, which corresponds to the output of argrelextrema for order=1. Likewise, for the other columns.

Summing

We can now use the cast function and the polars.sum function to sum row-wise across our columns. (Indeed, we won’t keep our rolling min columns — we’ll just keep the sums).

expr_list = [
    (
        pl.col("col1").rolling_min(
            window_size=_order * 2 + 1,
            min_periods=_order + 2,
            center=True
        )
        == pl.col("col1")
    ).cast(pl.UInt32)
    for _order in range(1, 7)
]
df.with_columns(pl.sum(expr_list).alias("min_freq"))
┌────────┬──────────┬──────────┐
│ row_nr ┆ col1     ┆ min_freq │
│ ---    ┆ ---      ┆ ---      │
│ u32    ┆ f64      ┆ u32      │
╞════════╪══════════╪══════════╡
│ 0      ┆ 46405.49 ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 1      ┆ 46407.36 ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 2      ┆ 46005.43 ┆ 1        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 3      ┆ 46174.0  ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 4      ┆ 30171.32 ┆ 6        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 5      ┆ 30457.01 ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 6      ┆ 30397.12 ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 7      ┆ 30373.53 ┆ 2        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 8      ┆ 47444.11 ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 9      ┆ 46461.14 ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 10     ┆ 46293.38 ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 11     ┆ 46287.97 ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 12     ┆ 30670.51 ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 13     ┆ 30616.18 ┆ 1        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 14     ┆ 30625.98 ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 15     ┆ 30529.9  ┆ 4        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 16     ┆ 46248.84 ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 17     ┆ 45744.77 ┆ 1        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 18     ┆ 45834.39 ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 19     ┆ 45787.0  ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 20     ┆ 30101.07 ┆ 1        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 21     ┆ 30281.89 ┆ 0        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 22     ┆ 29967.07 ┆ 6        │
├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 23     ┆ 30042.09 ┆ 0        │
└────────┴──────────┴──────────┘

I believe this is the result you were looking to obtain.

From here, I think you can expand the above code for rolling maximums.

Ties

One difference between this code and the argrelextrema code pertains to ties. If two values ​​tie for the minimum in any window, argrelextrema considers neither to be the minimum for the window. The code above considers both to be minimum values.

I’m not sure how likely this will be for the size of windows you have, or for the type of data.

Please update Polars to 0.13.38

The latest release of Polars contains some major improvements to the performance of rolling functions. (The announcement is on this Twitter thread.) You’ll want to take advantage of that by updating to the latest version.

Leave a Comment