1- import datetime
21from datetime import date
32from datetime import datetime
43from typing import Literal
87import polars as pl
98
109
11- def monthdelta (d1 : datetime , d2 : datetime ):
12- """Finner differansen mellom to måneder"""
10+ def monthdelta (d1 : datetime , d2 : datetime ) -> int :
11+ """Finner differansen mellom to måneder. """
1312 d1_ = pendulum .instance (d1 )
1413 d2_ = pendulum .instance (d2 )
1514 return (d1_ - d2_ ).in_months ()
1615
1716
1817def parse_period (period : str ) -> datetime :
19- """Parser en periode til datetime"""
18+ """Parser en periode til datetime. """
2019 return datetime .strptime (period , "%Y-%m" )
2120
2221
2322def multi_join (
2423 dfs : list [pl .DataFrame ],
2524 on : str ,
2625 how : Literal ["left" , "right" , "inner" , "cross" , "semi" , "anti" ] = "left" ,
27- ):
26+ ) -> pl . DataFrame :
2827 """Slår sammen flere Polars DataFrames sekvensielt på en spesifisert kolonne.
2928
3029 Utfører en kjedet sammenslåing (join) av flere DataFrames i en gitt liste basert på én felles kolonne.
@@ -46,6 +45,8 @@ def multi_join(
4645
4746
4847class DataSource :
48+ """Representerer en datakilde tilrettelagt for tidsbasert analyse og gruppering."""
49+
4950 def __init__ (
5051 self ,
5152 data : pl .DataFrame ,
@@ -136,7 +137,7 @@ def _gen_header(self, n: int, skip: int = 0):
136137 oldest : datetime = dates [- 1 - ((n * skip ) + n )]
137138 return f"{ self ._create_date (oldest )} - { self ._create_date (latest )} "
138139
139- def _base (self , n : int , * agg , ** named_aggs ):
140+ def _base (self , n : int , * agg : pl . Expr , ** named_aggs : pl . Expr ):
140141 """Utfører aggregering over dynamiske tidsvinduer og grupper.
141142
142143 Args:
@@ -156,7 +157,9 @@ def _base(self, n: int, *agg, **named_aggs):
156157 .agg (* agg , ** named_aggs )
157158 )
158159
159- def _base_w_header (self , n : int , skip : int = 0 , * agg , ** named_aggs ):
160+ def _base_w_header (
161+ self , n : int , skip : int = 0 , * agg : pl .Expr , ** named_aggs : pl .Expr
162+ ):
160163 """Genererer en overskrift for perioden og returnerer resultatet fra baseaggregering.
161164
162165 Kombinerer datoperiode-headeren med aggregerte resultater fra `_base`.
@@ -208,7 +211,7 @@ def n_month_percent(self, n: int, skip: int = 0) -> tuple[str, pl.DataFrame]:
208211 },
209212 )
210213
211- def n_percent_rolling (self , n : int , skip : int = 0 ):
214+ def n_percent_rolling (self , n : int , skip : int = 0 ) -> pl . DataFrame :
212215 """Beregner rullerende prosentvis endring over en periode og returnerer med datoperiode-header.
213216
214217 Denne metoden bruker en rullerende tidsvinduanalyse for å beregne prosentvis endring
@@ -225,14 +228,14 @@ def n_percent_rolling(self, n: int, skip: int = 0):
225228 """
226229
227230 def _gen_header (n : int , skip : int = 0 ):
228- """Lager overskrift for hver perioden"""
231+ """Lager overskrift for hver perioden. """
229232 dates = self .data .get_column (self ._date ).unique ().sort ()
230233 latest : datetime = dates [- 1 - (skip )]
231234 oldest : datetime = dates [- 1 - ((skip ) + n - 1 )]
232235 return f"{ self ._create_date (oldest )} - { self ._create_date (latest )} "
233236
234237 def map_test (x : pl .DataFrame ):
235- """Lager det rullende gjennomsnittet for hver periodegruppe"""
238+ """Lager det rullende gjennomsnittet for hver periodegruppe. """
236239 if x .shape [0 ] != n :
237240 x = x .with_columns (
238241 ** {self ._avg : pl .col (self ._col ).fill_null (strategy = "backward" )}
@@ -261,7 +264,7 @@ def map_test(x: pl.DataFrame):
261264 .explode (self ._avg )
262265 )
263266
264- def n_mean_rolling (self , n : int , skip : int = 0 ):
267+ def n_mean_rolling (self , n : int , skip : int = 0 ) -> pl . DataFrame :
265268 """Beregner et rullerende gjennomsnitt for hver gruppe i datasettet og returnerer med datoperiode-header.
266269
267270 Denne metoden beregner gjennomsnittet av verdiene innenfor et rullerende vindu på `n` måneder.
@@ -278,14 +281,14 @@ def n_mean_rolling(self, n: int, skip: int = 0):
278281 """
279282
280283 def _gen_header (n : int , skip : int = 0 ):
281- """Lager overskrift for hver perioden"""
284+ """Lager overskrift for hver perioden. """
282285 dates = self .data .get_column (self ._date ).unique ().sort ()
283286 latest : datetime = dates [- 1 - (skip )]
284287 oldest : datetime = dates [- 1 - ((skip ) + n - 1 )]
285288 return f"{ self ._create_date (oldest )} - { self ._create_date (latest )} "
286289
287290 def map_test (x : pl .DataFrame ):
288- """Lager det rullende gjennomsnittet for hver periodegruppe"""
291+ """Lager det rullende gjennomsnittet for hver periodegruppe. """
289292 if x .shape [0 ] != n :
290293 x = x .with_columns (
291294 ** {self ._avg : pl .col (self ._col ).fill_null (strategy = "backward" )}
@@ -374,14 +377,35 @@ def n_month_percent_compare(
374377 return header , joined
375378
376379
377- def rounded_average (df : pd .DataFrame , ordered_columns : list [str ]):
380+ def rounded_average (df : pd .DataFrame , ordered_columns : list [str ]) -> pd .Series :
381+ """Beregner gjennomsnitt per rad for utvalgte kolonner, avrundet til én desimal.
382+
383+ Args:
384+ df (pd.DataFrame): DataFrame med data.
385+ ordered_columns (list[str]): Liste med kolonnenavn som skal inkluderes i gjennomsnittet.
386+
387+ Returns:
388+ pd.Series: Gjennomsnitt per rad, avrundet til én desimal.
389+ """
378390 df_copy = df [ordered_columns ]
379391 df_copy = df_copy .round (1 )
380392 res = df_copy .sum (axis = "columns" ).div (len (ordered_columns ))
381393 return res .round (1 )
382394
383395
384- def calc_change_rate (df : pd .DataFrame , ordered_columns : list [str ], n : int = 1 ):
396+ def calc_change_rate (
397+ df : pd .DataFrame , ordered_columns : list [str ], n : int = 1
398+ ) -> pd .dateframe :
399+ """Beregner prosentvis endring mellom kolonner over n perioder.
400+
401+ Args:
402+ df (pd.DataFrame): DataFrame med data.
403+ ordered_columns (list[str]): Liste med kolonnenavn i rekkefølge.
404+ n (int, optional): Antall perioder tilbake for endringsberegning. Defaults to 1.
405+
406+ Returns:
407+ pd.DataFrame: Prosentvis endring per rad for hver kolonne (fra n. kolonne og fremover).
408+ """
385409 results = []
386410 for i in range (n , len (ordered_columns ), 1 ):
387411 col_present = ordered_columns [i ]
@@ -392,7 +416,16 @@ def calc_change_rate(df: pd.DataFrame, ordered_columns: list[str], n: int = 1):
392416 return pd .concat (results , axis = "columns" , keys = ordered_columns [n :])
393417
394418
395- def rolling_change_rate (df : pd .DataFrame , step : int = 1 ):
419+ def rolling_change_rate (df : pd .DataFrame , step : int = 1 ) -> pd .dateframe :
420+ """Beregner rullende prosentvis endring mellom kolonner med gitt steg.
421+
422+ Args:
423+ df (pd.DataFrame): DataFrame med kolonner som representerer perioder.
424+ step (int, optional): Antall kolonner å hoppe over for å beregne endring. Defaults to 1.
425+
426+ Returns:
427+ pd.DataFrame: Prosentvis endring per rad, med kolonner fra `step` og fremover.
428+ """
396429 results = []
397430 for i in range (step , len (df .columns ), step ):
398431 col_present = df .columns [i ]
0 commit comments