I am looking to implement a rolling window on a list, but instead of a fixed length of window, I would like to provide a rolling window list:
Something like this:
JavaScript
x
4
1
l1 = [5, 3, 8, 2, 10, 12, 13, 15, 22, 28]
2
l2 = [1, 2, 2, 2, 3, 4, 2, 3, 5, 3]
3
get_custom_roling( l1, l2, np.average)
4
and the result would be:
JavaScript
1
3
1
[5, 4, 5.5, 5, 6.67, .]
2
3
6.67 is calculated as average of 3 elements 10, 2, 8.
I implemented a slow solution, and every idea is welcome to make it quicker :):
JavaScript
1
27
27
1
import numpy as np
2
3
4
5
def get_the_list(end_point, number_points):
6
"""
7
example: get_the_list(6, 3) ==> [4, 5, 6]
8
example: get_the_list(9, 5) ==> [5, 6, 7, 8, 9]
9
"""
10
if np.isnan(number_points):
11
return []
12
number_points = int( number_points)
13
return list(range(end_point, end_point - number_points, -1 ))
14
15
def get_idx(s):
16
ss = list(enumerate(s) )
17
sss = (get_the_list(*elem) for elem in ss )
18
return sss
19
20
def get_custom_roling(s, ss, funct):
21
output_get_idx = get_idx(ss)
22
agg_stuff = [s[elem] for elem in output_get_idx]
23
res_agg_stuff = [ funct(elem) for elem in agg_stuff ]
24
res_agg_stuff = eiu.pd.Series(data=res_agg_stuff, index = s.index)
25
return res_agg_stuff
26
27
Advertisement
Answer
Pandas custom window rolling allows you to modify size of window.
Simple explanation: start
and end
arrays hold values of indexes to make slices of your data.
JavaScript
1
3
1
#start = [0 0 1 2 2 2 5 5 4 7]
2
#end = [1 2 3 4 5 6 7 8 9 10]
3
Arguments passed to get_window_bounds
are given by BaseIndexer.
JavaScript
1
19
19
1
import pandas as pd
2
import numpy as np
3
from pandas.api.indexers import BaseIndexer
4
from typing import Optional, Tuple
5
6
7
class CustomIndexer(BaseIndexer):
8
9
def get_window_bounds(self,
10
num_values: int = 0,
11
min_periods: Optional[int] = None,
12
center: Optional[bool] = None,
13
closed: Optional[str] = None
14
) -> Tuple[np.ndarray, np.ndarray]:
15
16
end = np.arange(1, num_values+1, dtype=np.int64)
17
start = end - np.array(self.custom_name_whatever, dtype=np.int64)
18
return start, end
19
JavaScript
1
9
1
df = pd.DataFrame({"l1": [5, 3, 8, 2, 10, 12, 13, 15, 22, 28],
2
"l2": [1, 2, 2, 2, 3, 4, 2, 3, 5, 3]})
3
4
indexer = CustomIndexer(custom_name_whatever=df.l2)
5
6
df["variable_mean"] = df.l1.rolling(indexer).mean()
7
8
print(df)
9
Outputs:
JavaScript
1
12
12
1
l1 l2 variable_mean
2
0 5 1 5.000000
3
1 3 2 4.000000
4
2 8 2 5.500000
5
3 2 2 5.000000
6
4 10 3 6.666667
7
5 12 4 8.000000
8
6 13 2 12.500000
9
7 15 3 13.333333
10
8 22 5 14.400000
11
9 28 3 21.666667
12