123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935 |
- from datetime import (
- datetime,
- timedelta,
- )
- import numpy as np
- import pytest
- from pandas.compat import (
- is_platform_arm,
- is_platform_mac,
- is_platform_power,
- )
- from pandas import (
- DataFrame,
- DatetimeIndex,
- MultiIndex,
- Series,
- Timedelta,
- Timestamp,
- date_range,
- period_range,
- to_datetime,
- to_timedelta,
- )
- import pandas._testing as tm
- from pandas.api.indexers import BaseIndexer
- from pandas.core.indexers.objects import VariableOffsetWindowIndexer
- from pandas.tseries.offsets import BusinessDay
- def test_doc_string():
- df = DataFrame({"B": [0, 1, 2, np.nan, 4]})
- df
- df.rolling(2).sum()
- df.rolling(2, min_periods=1).sum()
- def test_constructor(frame_or_series):
- # GH 12669
- c = frame_or_series(range(5)).rolling
- # valid
- c(0)
- c(window=2)
- c(window=2, min_periods=1)
- c(window=2, min_periods=1, center=True)
- c(window=2, min_periods=1, center=False)
- # GH 13383
- msg = "window must be an integer 0 or greater"
- with pytest.raises(ValueError, match=msg):
- c(-1)
- @pytest.mark.parametrize("w", [2.0, "foo", np.array([2])])
- def test_invalid_constructor(frame_or_series, w):
- # not valid
- c = frame_or_series(range(5)).rolling
- msg = "|".join(
- [
- "window must be an integer",
- "passed window foo is not compatible with a datetimelike index",
- ]
- )
- with pytest.raises(ValueError, match=msg):
- c(window=w)
- msg = "min_periods must be an integer"
- with pytest.raises(ValueError, match=msg):
- c(window=2, min_periods=w)
- msg = "center must be a boolean"
- with pytest.raises(ValueError, match=msg):
- c(window=2, min_periods=1, center=w)
- @pytest.mark.parametrize(
- "window",
- [
- timedelta(days=3),
- Timedelta(days=3),
- "3D",
- VariableOffsetWindowIndexer(
- index=date_range("2015-12-25", periods=5), offset=BusinessDay(1)
- ),
- ],
- )
- def test_freq_window_not_implemented(window):
- # GH 15354
- df = DataFrame(
- np.arange(10),
- index=date_range("2015-12-24", periods=10, freq="D"),
- )
- with pytest.raises(
- NotImplementedError, match="step is not supported with frequency windows"
- ):
- df.rolling("3D", step=3)
- @pytest.mark.parametrize("agg", ["cov", "corr"])
- def test_step_not_implemented_for_cov_corr(agg):
- # GH 15354
- roll = DataFrame(range(2)).rolling(1, step=2)
- with pytest.raises(NotImplementedError, match="step not implemented"):
- getattr(roll, agg)()
- @pytest.mark.parametrize("window", [timedelta(days=3), Timedelta(days=3)])
- def test_constructor_with_timedelta_window(window):
- # GH 15440
- n = 10
- df = DataFrame(
- {"value": np.arange(n)},
- index=date_range("2015-12-24", periods=n, freq="D"),
- )
- expected_data = np.append([0.0, 1.0], np.arange(3.0, 27.0, 3))
- result = df.rolling(window=window).sum()
- expected = DataFrame(
- {"value": expected_data},
- index=date_range("2015-12-24", periods=n, freq="D"),
- )
- tm.assert_frame_equal(result, expected)
- expected = df.rolling("3D").sum()
- tm.assert_frame_equal(result, expected)
- @pytest.mark.parametrize("window", [timedelta(days=3), Timedelta(days=3), "3D"])
- def test_constructor_timedelta_window_and_minperiods(window, raw):
- # GH 15305
- n = 10
- df = DataFrame(
- {"value": np.arange(n)},
- index=date_range("2017-08-08", periods=n, freq="D"),
- )
- expected = DataFrame(
- {"value": np.append([np.NaN, 1.0], np.arange(3.0, 27.0, 3))},
- index=date_range("2017-08-08", periods=n, freq="D"),
- )
- result_roll_sum = df.rolling(window=window, min_periods=2).sum()
- result_roll_generic = df.rolling(window=window, min_periods=2).apply(sum, raw=raw)
- tm.assert_frame_equal(result_roll_sum, expected)
- tm.assert_frame_equal(result_roll_generic, expected)
- def test_closed_fixed(closed, arithmetic_win_operators):
- # GH 34315
- func_name = arithmetic_win_operators
- df_fixed = DataFrame({"A": [0, 1, 2, 3, 4]})
- df_time = DataFrame({"A": [0, 1, 2, 3, 4]}, index=date_range("2020", periods=5))
- result = getattr(
- df_fixed.rolling(2, closed=closed, min_periods=1),
- func_name,
- )()
- expected = getattr(
- df_time.rolling("2D", closed=closed, min_periods=1),
- func_name,
- )().reset_index(drop=True)
- tm.assert_frame_equal(result, expected)
- @pytest.mark.parametrize(
- "closed, window_selections",
- [
- (
- "both",
- [
- [True, True, False, False, False],
- [True, True, True, False, False],
- [False, True, True, True, False],
- [False, False, True, True, True],
- [False, False, False, True, True],
- ],
- ),
- (
- "left",
- [
- [True, False, False, False, False],
- [True, True, False, False, False],
- [False, True, True, False, False],
- [False, False, True, True, False],
- [False, False, False, True, True],
- ],
- ),
- (
- "right",
- [
- [True, True, False, False, False],
- [False, True, True, False, False],
- [False, False, True, True, False],
- [False, False, False, True, True],
- [False, False, False, False, True],
- ],
- ),
- (
- "neither",
- [
- [True, False, False, False, False],
- [False, True, False, False, False],
- [False, False, True, False, False],
- [False, False, False, True, False],
- [False, False, False, False, True],
- ],
- ),
- ],
- )
- def test_datetimelike_centered_selections(
- closed, window_selections, arithmetic_win_operators
- ):
- # GH 34315
- func_name = arithmetic_win_operators
- df_time = DataFrame(
- {"A": [0.0, 1.0, 2.0, 3.0, 4.0]}, index=date_range("2020", periods=5)
- )
- expected = DataFrame(
- {"A": [getattr(df_time["A"].iloc[s], func_name)() for s in window_selections]},
- index=date_range("2020", periods=5),
- )
- if func_name == "sem":
- kwargs = {"ddof": 0}
- else:
- kwargs = {}
- result = getattr(
- df_time.rolling("2D", closed=closed, min_periods=1, center=True),
- func_name,
- )(**kwargs)
- tm.assert_frame_equal(result, expected, check_dtype=False)
- @pytest.mark.parametrize(
- "window,closed,expected",
- [
- ("3s", "right", [3.0, 3.0, 3.0]),
- ("3s", "both", [3.0, 3.0, 3.0]),
- ("3s", "left", [3.0, 3.0, 3.0]),
- ("3s", "neither", [3.0, 3.0, 3.0]),
- ("2s", "right", [3.0, 2.0, 2.0]),
- ("2s", "both", [3.0, 3.0, 3.0]),
- ("2s", "left", [1.0, 3.0, 3.0]),
- ("2s", "neither", [1.0, 2.0, 2.0]),
- ],
- )
- def test_datetimelike_centered_offset_covers_all(
- window, closed, expected, frame_or_series
- ):
- # GH 42753
- index = [
- Timestamp("20130101 09:00:01"),
- Timestamp("20130101 09:00:02"),
- Timestamp("20130101 09:00:02"),
- ]
- df = frame_or_series([1, 1, 1], index=index)
- result = df.rolling(window, closed=closed, center=True).sum()
- expected = frame_or_series(expected, index=index)
- tm.assert_equal(result, expected)
- @pytest.mark.parametrize(
- "window,closed,expected",
- [
- ("2D", "right", [4, 4, 4, 4, 4, 4, 2, 2]),
- ("2D", "left", [2, 2, 4, 4, 4, 4, 4, 4]),
- ("2D", "both", [4, 4, 6, 6, 6, 6, 4, 4]),
- ("2D", "neither", [2, 2, 2, 2, 2, 2, 2, 2]),
- ],
- )
- def test_datetimelike_nonunique_index_centering(
- window, closed, expected, frame_or_series
- ):
- index = DatetimeIndex(
- [
- "2020-01-01",
- "2020-01-01",
- "2020-01-02",
- "2020-01-02",
- "2020-01-03",
- "2020-01-03",
- "2020-01-04",
- "2020-01-04",
- ]
- )
- df = frame_or_series([1] * 8, index=index, dtype=float)
- expected = frame_or_series(expected, index=index, dtype=float)
- result = df.rolling(window, center=True, closed=closed).sum()
- tm.assert_equal(result, expected)
- def test_even_number_window_alignment():
- # see discussion in GH 38780
- s = Series(range(3), index=date_range(start="2020-01-01", freq="D", periods=3))
- # behavior of index- and datetime-based windows differs here!
- # s.rolling(window=2, min_periods=1, center=True).mean()
- result = s.rolling(window="2D", min_periods=1, center=True).mean()
- expected = Series([0.5, 1.5, 2], index=s.index)
- tm.assert_series_equal(result, expected)
- def test_closed_fixed_binary_col(center, step):
- # GH 34315
- data = [0, 1, 1, 0, 0, 1, 0, 1]
- df = DataFrame(
- {"binary_col": data},
- index=date_range(start="2020-01-01", freq="min", periods=len(data)),
- )
- if center:
- expected_data = [2 / 3, 0.5, 0.4, 0.5, 0.428571, 0.5, 0.571429, 0.5]
- else:
- expected_data = [np.nan, 0, 0.5, 2 / 3, 0.5, 0.4, 0.5, 0.428571]
- expected = DataFrame(
- expected_data,
- columns=["binary_col"],
- index=date_range(start="2020-01-01", freq="min", periods=len(expected_data)),
- )[::step]
- rolling = df.rolling(
- window=len(df), closed="left", min_periods=1, center=center, step=step
- )
- result = rolling.mean()
- tm.assert_frame_equal(result, expected)
- @pytest.mark.parametrize("closed", ["neither", "left"])
- def test_closed_empty(closed, arithmetic_win_operators):
- # GH 26005
- func_name = arithmetic_win_operators
- ser = Series(data=np.arange(5), index=date_range("2000", periods=5, freq="2D"))
- roll = ser.rolling("1D", closed=closed)
- result = getattr(roll, func_name)()
- expected = Series([np.nan] * 5, index=ser.index)
- tm.assert_series_equal(result, expected)
- @pytest.mark.parametrize("func", ["min", "max"])
- def test_closed_one_entry(func):
- # GH24718
- ser = Series(data=[2], index=date_range("2000", periods=1))
- result = getattr(ser.rolling("10D", closed="left"), func)()
- tm.assert_series_equal(result, Series([np.nan], index=ser.index))
- @pytest.mark.parametrize("func", ["min", "max"])
- def test_closed_one_entry_groupby(func):
- # GH24718
- ser = DataFrame(
- data={"A": [1, 1, 2], "B": [3, 2, 1]},
- index=date_range("2000", periods=3),
- )
- result = getattr(
- ser.groupby("A", sort=False)["B"].rolling("10D", closed="left"), func
- )()
- exp_idx = MultiIndex.from_arrays(arrays=[[1, 1, 2], ser.index], names=("A", None))
- expected = Series(data=[np.nan, 3, np.nan], index=exp_idx, name="B")
- tm.assert_series_equal(result, expected)
- @pytest.mark.parametrize("input_dtype", ["int", "float"])
- @pytest.mark.parametrize(
- "func,closed,expected",
- [
- ("min", "right", [0.0, 0, 0, 1, 2, 3, 4, 5, 6, 7]),
- ("min", "both", [0.0, 0, 0, 0, 1, 2, 3, 4, 5, 6]),
- ("min", "neither", [np.nan, 0, 0, 1, 2, 3, 4, 5, 6, 7]),
- ("min", "left", [np.nan, 0, 0, 0, 1, 2, 3, 4, 5, 6]),
- ("max", "right", [0.0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
- ("max", "both", [0.0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
- ("max", "neither", [np.nan, 0, 1, 2, 3, 4, 5, 6, 7, 8]),
- ("max", "left", [np.nan, 0, 1, 2, 3, 4, 5, 6, 7, 8]),
- ],
- )
- def test_closed_min_max_datetime(input_dtype, func, closed, expected):
- # see gh-21704
- ser = Series(
- data=np.arange(10).astype(input_dtype),
- index=date_range("2000", periods=10),
- )
- result = getattr(ser.rolling("3D", closed=closed), func)()
- expected = Series(expected, index=ser.index)
- tm.assert_series_equal(result, expected)
- def test_closed_uneven():
- # see gh-21704
- ser = Series(data=np.arange(10), index=date_range("2000", periods=10))
- # uneven
- ser = ser.drop(index=ser.index[[1, 5]])
- result = ser.rolling("3D", closed="left").min()
- expected = Series([np.nan, 0, 0, 2, 3, 4, 6, 6], index=ser.index)
- tm.assert_series_equal(result, expected)
- @pytest.mark.parametrize(
- "func,closed,expected",
- [
- ("min", "right", [np.nan, 0, 0, 1, 2, 3, 4, 5, np.nan, np.nan]),
- ("min", "both", [np.nan, 0, 0, 0, 1, 2, 3, 4, 5, np.nan]),
- ("min", "neither", [np.nan, np.nan, 0, 1, 2, 3, 4, 5, np.nan, np.nan]),
- ("min", "left", [np.nan, np.nan, 0, 0, 1, 2, 3, 4, 5, np.nan]),
- ("max", "right", [np.nan, 1, 2, 3, 4, 5, 6, 6, np.nan, np.nan]),
- ("max", "both", [np.nan, 1, 2, 3, 4, 5, 6, 6, 6, np.nan]),
- ("max", "neither", [np.nan, np.nan, 1, 2, 3, 4, 5, 6, np.nan, np.nan]),
- ("max", "left", [np.nan, np.nan, 1, 2, 3, 4, 5, 6, 6, np.nan]),
- ],
- )
- def test_closed_min_max_minp(func, closed, expected):
- # see gh-21704
- ser = Series(data=np.arange(10), index=date_range("2000", periods=10))
- # Explicit cast to float to avoid implicit cast when setting nan
- ser = ser.astype("float")
- ser[ser.index[-3:]] = np.nan
- result = getattr(ser.rolling("3D", min_periods=2, closed=closed), func)()
- expected = Series(expected, index=ser.index)
- tm.assert_series_equal(result, expected)
- @pytest.mark.parametrize(
- "closed,expected",
- [
- ("right", [0, 0.5, 1, 2, 3, 4, 5, 6, 7, 8]),
- ("both", [0, 0.5, 1, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5]),
- ("neither", [np.nan, 0, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5]),
- ("left", [np.nan, 0, 0.5, 1, 2, 3, 4, 5, 6, 7]),
- ],
- )
- def test_closed_median_quantile(closed, expected):
- # GH 26005
- ser = Series(data=np.arange(10), index=date_range("2000", periods=10))
- roll = ser.rolling("3D", closed=closed)
- expected = Series(expected, index=ser.index)
- result = roll.median()
- tm.assert_series_equal(result, expected)
- result = roll.quantile(0.5)
- tm.assert_series_equal(result, expected)
- @pytest.mark.parametrize("roller", ["1s", 1])
- def tests_empty_df_rolling(roller):
- # GH 15819 Verifies that datetime and integer rolling windows can be
- # applied to empty DataFrames
- expected = DataFrame()
- result = DataFrame().rolling(roller).sum()
- tm.assert_frame_equal(result, expected)
- # Verifies that datetime and integer rolling windows can be applied to
- # empty DataFrames with datetime index
- expected = DataFrame(index=DatetimeIndex([]))
- result = DataFrame(index=DatetimeIndex([])).rolling(roller).sum()
- tm.assert_frame_equal(result, expected)
- def test_empty_window_median_quantile():
- # GH 26005
- expected = Series([np.nan, np.nan, np.nan])
- roll = Series(np.arange(3)).rolling(0)
- result = roll.median()
- tm.assert_series_equal(result, expected)
- result = roll.quantile(0.1)
- tm.assert_series_equal(result, expected)
- def test_missing_minp_zero():
- # https://github.com/pandas-dev/pandas/pull/18921
- # minp=0
- x = Series([np.nan])
- result = x.rolling(1, min_periods=0).sum()
- expected = Series([0.0])
- tm.assert_series_equal(result, expected)
- # minp=1
- result = x.rolling(1, min_periods=1).sum()
- expected = Series([np.nan])
- tm.assert_series_equal(result, expected)
- def test_missing_minp_zero_variable():
- # https://github.com/pandas-dev/pandas/pull/18921
- x = Series(
- [np.nan] * 4,
- index=DatetimeIndex(["2017-01-01", "2017-01-04", "2017-01-06", "2017-01-07"]),
- )
- result = x.rolling(Timedelta("2d"), min_periods=0).sum()
- expected = Series(0.0, index=x.index)
- tm.assert_series_equal(result, expected)
- def test_multi_index_names():
- # GH 16789, 16825
- cols = MultiIndex.from_product([["A", "B"], ["C", "D", "E"]], names=["1", "2"])
- df = DataFrame(np.ones((10, 6)), columns=cols)
- result = df.rolling(3).cov()
- tm.assert_index_equal(result.columns, df.columns)
- assert result.index.names == [None, "1", "2"]
- def test_rolling_axis_sum(axis_frame):
- # see gh-23372.
- df = DataFrame(np.ones((10, 20)))
- axis = df._get_axis_number(axis_frame)
- if axis == 0:
- expected = DataFrame({i: [np.nan] * 2 + [3.0] * 8 for i in range(20)})
- else:
- # axis == 1
- expected = DataFrame([[np.nan] * 2 + [3.0] * 18] * 10)
- result = df.rolling(3, axis=axis_frame).sum()
- tm.assert_frame_equal(result, expected)
- def test_rolling_axis_count(axis_frame):
- # see gh-26055
- df = DataFrame({"x": range(3), "y": range(3)})
- axis = df._get_axis_number(axis_frame)
- if axis in [0, "index"]:
- expected = DataFrame({"x": [1.0, 2.0, 2.0], "y": [1.0, 2.0, 2.0]})
- else:
- expected = DataFrame({"x": [1.0, 1.0, 1.0], "y": [2.0, 2.0, 2.0]})
- result = df.rolling(2, axis=axis_frame, min_periods=0).count()
- tm.assert_frame_equal(result, expected)
- def test_readonly_array():
- # GH-27766
- arr = np.array([1, 3, np.nan, 3, 5])
- arr.setflags(write=False)
- result = Series(arr).rolling(2).mean()
- expected = Series([np.nan, 2, np.nan, np.nan, 4])
- tm.assert_series_equal(result, expected)
- def test_rolling_datetime(axis_frame, tz_naive_fixture):
- # GH-28192
- tz = tz_naive_fixture
- df = DataFrame(
- {i: [1] * 2 for i in date_range("2019-8-01", "2019-08-03", freq="D", tz=tz)}
- )
- if axis_frame in [0, "index"]:
- result = df.T.rolling("2D", axis=axis_frame).sum().T
- else:
- result = df.rolling("2D", axis=axis_frame).sum()
- expected = DataFrame(
- {
- **{
- i: [1.0] * 2
- for i in date_range("2019-8-01", periods=1, freq="D", tz=tz)
- },
- **{
- i: [2.0] * 2
- for i in date_range("2019-8-02", "2019-8-03", freq="D", tz=tz)
- },
- }
- )
- tm.assert_frame_equal(result, expected)
- @pytest.mark.parametrize(
- "center, expected_data",
- [
- (
- True,
- (
- [88.0] * 7
- + [97.0] * 9
- + [98.0]
- + [99.0] * 21
- + [95.0] * 16
- + [93.0] * 5
- + [89.0] * 5
- + [96.0] * 21
- + [94.0] * 14
- + [90.0] * 13
- + [88.0] * 2
- + [90.0] * 9
- + [96.0] * 21
- + [95.0] * 6
- + [91.0]
- + [87.0] * 6
- + [92.0] * 21
- + [83.0] * 2
- + [86.0] * 10
- + [87.0] * 5
- + [98.0] * 21
- + [97.0] * 14
- + [93.0] * 7
- + [87.0] * 4
- + [86.0] * 4
- + [95.0] * 21
- + [85.0] * 14
- + [83.0] * 2
- + [76.0] * 5
- + [81.0] * 2
- + [98.0] * 21
- + [95.0] * 14
- + [91.0] * 7
- + [86.0]
- + [93.0] * 3
- + [95.0] * 29
- + [77.0] * 2
- ),
- ),
- (
- False,
- (
- [np.nan] * 2
- + [88.0] * 16
- + [97.0] * 9
- + [98.0]
- + [99.0] * 21
- + [95.0] * 16
- + [93.0] * 5
- + [89.0] * 5
- + [96.0] * 21
- + [94.0] * 14
- + [90.0] * 13
- + [88.0] * 2
- + [90.0] * 9
- + [96.0] * 21
- + [95.0] * 6
- + [91.0]
- + [87.0] * 6
- + [92.0] * 21
- + [83.0] * 2
- + [86.0] * 10
- + [87.0] * 5
- + [98.0] * 21
- + [97.0] * 14
- + [93.0] * 7
- + [87.0] * 4
- + [86.0] * 4
- + [95.0] * 21
- + [85.0] * 14
- + [83.0] * 2
- + [76.0] * 5
- + [81.0] * 2
- + [98.0] * 21
- + [95.0] * 14
- + [91.0] * 7
- + [86.0]
- + [93.0] * 3
- + [95.0] * 20
- ),
- ),
- ],
- )
- def test_rolling_window_as_string(center, expected_data):
- # see gh-22590
- date_today = datetime.now()
- days = date_range(date_today, date_today + timedelta(365), freq="D")
- npr = np.random.RandomState(seed=421)
- data = npr.randint(1, high=100, size=len(days))
- df = DataFrame({"DateCol": days, "metric": data})
- df.set_index("DateCol", inplace=True)
- result = df.rolling(window="21D", min_periods=2, closed="left", center=center)[
- "metric"
- ].agg("max")
- index = days.rename("DateCol")
- index = index._with_freq(None)
- expected = Series(expected_data, index=index, name="metric")
- tm.assert_series_equal(result, expected)
- def test_min_periods1():
- # GH#6795
- df = DataFrame([0, 1, 2, 1, 0], columns=["a"])
- result = df["a"].rolling(3, center=True, min_periods=1).max()
- expected = Series([1.0, 2.0, 2.0, 2.0, 1.0], name="a")
- tm.assert_series_equal(result, expected)
- def test_rolling_count_with_min_periods(frame_or_series):
- # GH 26996
- result = frame_or_series(range(5)).rolling(3, min_periods=3).count()
- expected = frame_or_series([np.nan, np.nan, 3.0, 3.0, 3.0])
- tm.assert_equal(result, expected)
- def test_rolling_count_default_min_periods_with_null_values(frame_or_series):
- # GH 26996
- values = [1, 2, 3, np.nan, 4, 5, 6]
- expected_counts = [1.0, 2.0, 3.0, 2.0, 2.0, 2.0, 3.0]
- # GH 31302
- result = frame_or_series(values).rolling(3, min_periods=0).count()
- expected = frame_or_series(expected_counts)
- tm.assert_equal(result, expected)
- @pytest.mark.parametrize(
- "df,expected,window,min_periods",
- [
- (
- DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}),
- [
- ({"A": [1], "B": [4]}, [0]),
- ({"A": [1, 2], "B": [4, 5]}, [0, 1]),
- ({"A": [1, 2, 3], "B": [4, 5, 6]}, [0, 1, 2]),
- ],
- 3,
- None,
- ),
- (
- DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}),
- [
- ({"A": [1], "B": [4]}, [0]),
- ({"A": [1, 2], "B": [4, 5]}, [0, 1]),
- ({"A": [2, 3], "B": [5, 6]}, [1, 2]),
- ],
- 2,
- 1,
- ),
- (
- DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}),
- [
- ({"A": [1], "B": [4]}, [0]),
- ({"A": [1, 2], "B": [4, 5]}, [0, 1]),
- ({"A": [2, 3], "B": [5, 6]}, [1, 2]),
- ],
- 2,
- 2,
- ),
- (
- DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}),
- [
- ({"A": [1], "B": [4]}, [0]),
- ({"A": [2], "B": [5]}, [1]),
- ({"A": [3], "B": [6]}, [2]),
- ],
- 1,
- 1,
- ),
- (
- DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}),
- [
- ({"A": [1], "B": [4]}, [0]),
- ({"A": [2], "B": [5]}, [1]),
- ({"A": [3], "B": [6]}, [2]),
- ],
- 1,
- 0,
- ),
- (DataFrame({"A": [1], "B": [4]}), [], 2, None),
- (DataFrame({"A": [1], "B": [4]}), [], 2, 1),
- (DataFrame(), [({}, [])], 2, None),
- (
- DataFrame({"A": [1, np.nan, 3], "B": [np.nan, 5, 6]}),
- [
- ({"A": [1.0], "B": [np.nan]}, [0]),
- ({"A": [1, np.nan], "B": [np.nan, 5]}, [0, 1]),
- ({"A": [1, np.nan, 3], "B": [np.nan, 5, 6]}, [0, 1, 2]),
- ],
- 3,
- 2,
- ),
- ],
- )
- def test_iter_rolling_dataframe(df, expected, window, min_periods):
- # GH 11704
- expected = [DataFrame(values, index=index) for (values, index) in expected]
- for expected, actual in zip(expected, df.rolling(window, min_periods=min_periods)):
- tm.assert_frame_equal(actual, expected)
- @pytest.mark.parametrize(
- "expected,window",
- [
- (
- [
- ({"A": [1], "B": [4]}, [0]),
- ({"A": [1, 2], "B": [4, 5]}, [0, 1]),
- ({"A": [2, 3], "B": [5, 6]}, [1, 2]),
- ],
- "2D",
- ),
- (
- [
- ({"A": [1], "B": [4]}, [0]),
- ({"A": [1, 2], "B": [4, 5]}, [0, 1]),
- ({"A": [1, 2, 3], "B": [4, 5, 6]}, [0, 1, 2]),
- ],
- "3D",
- ),
- (
- [
- ({"A": [1], "B": [4]}, [0]),
- ({"A": [2], "B": [5]}, [1]),
- ({"A": [3], "B": [6]}, [2]),
- ],
- "1D",
- ),
- ],
- )
- def test_iter_rolling_on_dataframe(expected, window):
- # GH 11704, 40373
- df = DataFrame(
- {
- "A": [1, 2, 3, 4, 5],
- "B": [4, 5, 6, 7, 8],
- "C": date_range(start="2016-01-01", periods=5, freq="D"),
- }
- )
- expected = [
- DataFrame(values, index=df.loc[index, "C"]) for (values, index) in expected
- ]
- for expected, actual in zip(expected, df.rolling(window, on="C")):
- tm.assert_frame_equal(actual, expected)
- def test_iter_rolling_on_dataframe_unordered():
- # GH 43386
- df = DataFrame({"a": ["x", "y", "x"], "b": [0, 1, 2]})
- results = list(df.groupby("a").rolling(2))
- expecteds = [df.iloc[idx, [1]] for idx in [[0], [0, 2], [1]]]
- for result, expected in zip(results, expecteds):
- tm.assert_frame_equal(result, expected)
- @pytest.mark.parametrize(
- "ser,expected,window, min_periods",
- [
- (
- Series([1, 2, 3]),
- [([1], [0]), ([1, 2], [0, 1]), ([1, 2, 3], [0, 1, 2])],
- 3,
- None,
- ),
- (
- Series([1, 2, 3]),
- [([1], [0]), ([1, 2], [0, 1]), ([1, 2, 3], [0, 1, 2])],
- 3,
- 1,
- ),
- (
- Series([1, 2, 3]),
- [([1], [0]), ([1, 2], [0, 1]), ([2, 3], [1, 2])],
- 2,
- 1,
- ),
- (
- Series([1, 2, 3]),
- [([1], [0]), ([1, 2], [0, 1]), ([2, 3], [1, 2])],
- 2,
- 2,
- ),
- (Series([1, 2, 3]), [([1], [0]), ([2], [1]), ([3], [2])], 1, 0),
- (Series([1, 2, 3]), [([1], [0]), ([2], [1]), ([3], [2])], 1, 1),
- (Series([1, 2]), [([1], [0]), ([1, 2], [0, 1])], 2, 0),
- (Series([], dtype="int64"), [], 2, 1),
- ],
- )
- def test_iter_rolling_series(ser, expected, window, min_periods):
- # GH 11704
- expected = [Series(values, index=index) for (values, index) in expected]
- for expected, actual in zip(expected, ser.rolling(window, min_periods=min_periods)):
- tm.assert_series_equal(actual, expected)
- @pytest.mark.parametrize(
- "expected,expected_index,window",
- [
- (
- [[0], [1], [2], [3], [4]],
- [
- date_range("2020-01-01", periods=1, freq="D"),
- date_range("2020-01-02", periods=1, freq="D"),
- date_range("2020-01-03", periods=1, freq="D"),
- date_range("2020-01-04", periods=1, freq="D"),
- date_range("2020-01-05", periods=1, freq="D"),
- ],
- "1D",
- ),
- (
- [[0], [0, 1], [1, 2], [2, 3], [3, 4]],
- [
- date_range("2020-01-01", periods=1, freq="D"),
- date_range("2020-01-01", periods=2, freq="D"),
- date_range("2020-01-02", periods=2, freq="D"),
- date_range("2020-01-03", periods=2, freq="D"),
- date_range("2020-01-04", periods=2, freq="D"),
- ],
- "2D",
- ),
- (
- [[0], [0, 1], [0, 1, 2], [1, 2, 3], [2, 3, 4]],
- [
- date_range("2020-01-01", periods=1, freq="D"),
- date_range("2020-01-01", periods=2, freq="D"),
- date_range("2020-01-01", periods=3, freq="D"),
- date_range("2020-01-02", periods=3, freq="D"),
- date_range("2020-01-03", periods=3, freq="D"),
- ],
- "3D",
- ),
- ],
- )
- def test_iter_rolling_datetime(expected, expected_index, window):
- # GH 11704
- ser = Series(range(5), index=date_range(start="2020-01-01", periods=5, freq="D"))
- expected = [
- Series(values, index=idx) for (values, idx) in zip(expected, expected_index)
- ]
- for expected, actual in zip(expected, ser.rolling(window)):
- tm.assert_series_equal(actual, expected)
- @pytest.mark.parametrize(
- "grouping,_index",
- [
- (
- {"level": 0},
- MultiIndex.from_tuples(
- [(0, 0), (0, 0), (1, 1), (1, 1), (1, 1)], names=[None, None]
- ),
- ),
- (
- {"by": "X"},
- MultiIndex.from_tuples(
- [(0, 0), (1, 0), (2, 1), (3, 1), (4, 1)], names=["X", None]
- ),
- ),
- ],
- )
- def test_rolling_positional_argument(grouping, _index, raw):
- # GH 34605
- def scaled_sum(*args):
- if len(args) < 2:
- raise ValueError("The function needs two arguments")
- array, scale = args
- return array.sum() / scale
- df = DataFrame(data={"X": range(5)}, index=[0, 0, 1, 1, 1])
- expected = DataFrame(data={"X": [0.0, 0.5, 1.0, 1.5, 2.0]}, index=_index)
- # GH 40341
- if "by" in grouping:
- expected = expected.drop(columns="X", errors="ignore")
- result = df.groupby(**grouping).rolling(1).apply(scaled_sum, raw=raw, args=(2,))
- tm.assert_frame_equal(result, expected)
- @pytest.mark.parametrize("add", [0.0, 2.0])
- def test_rolling_numerical_accuracy_kahan_mean(add):
- # GH: 36031 implementing kahan summation
- df = DataFrame(
- {"A": [3002399751580331.0 + add, -0.0, -0.0]},
- index=[
- Timestamp("19700101 09:00:00"),
- Timestamp("19700101 09:00:03"),
- Timestamp("19700101 09:00:06"),
- ],
- )
- result = (
- df.resample("1s").ffill().rolling("3s", closed="left", min_periods=3).mean()
- )
- dates = date_range("19700101 09:00:00", periods=7, freq="S")
- expected = DataFrame(
- {
- "A": [
- np.nan,
- np.nan,
- np.nan,
- 3002399751580330.5,
- 2001599834386887.25,
- 1000799917193443.625,
- 0.0,
- ]
- },
- index=dates,
- )
- tm.assert_frame_equal(result, expected)
- def test_rolling_numerical_accuracy_kahan_sum():
- # GH: 13254
- df = DataFrame([2.186, -1.647, 0.0, 0.0, 0.0, 0.0], columns=["x"])
- result = df["x"].rolling(3).sum()
- expected = Series([np.nan, np.nan, 0.539, -1.647, 0.0, 0.0], name="x")
- tm.assert_series_equal(result, expected)
- def test_rolling_numerical_accuracy_jump():
- # GH: 32761
- index = date_range(start="2020-01-01", end="2020-01-02", freq="60s").append(
- DatetimeIndex(["2020-01-03"])
- )
- data = np.random.rand(len(index))
- df = DataFrame({"data": data}, index=index)
- result = df.rolling("60s").mean()
- tm.assert_frame_equal(result, df[["data"]])
- def test_rolling_numerical_accuracy_small_values():
- # GH: 10319
- s = Series(
- data=[0.00012456, 0.0003, -0.0, -0.0],
- index=date_range("1999-02-03", "1999-02-06"),
- )
- result = s.rolling(1).mean()
- tm.assert_series_equal(result, s)
- def test_rolling_numerical_too_large_numbers():
- # GH: 11645
- dates = date_range("2015-01-01", periods=10, freq="D")
- ds = Series(data=range(10), index=dates, dtype=np.float64)
- ds[2] = -9e33
- result = ds.rolling(5).mean()
- expected = Series(
- [
- np.nan,
- np.nan,
- np.nan,
- np.nan,
- -1.8e33,
- -1.8e33,
- -1.8e33,
- 5.0,
- 6.0,
- 7.0,
- ],
- index=dates,
- )
- tm.assert_series_equal(result, expected)
- @pytest.mark.parametrize(
- ("func", "value"),
- [("sum", 2.0), ("max", 1.0), ("min", 1.0), ("mean", 1.0), ("median", 1.0)],
- )
- def test_rolling_mixed_dtypes_axis_1(func, value):
- # GH: 20649
- df = DataFrame(1, index=[1, 2], columns=["a", "b", "c"])
- df["c"] = 1.0
- result = getattr(df.rolling(window=2, min_periods=1, axis=1), func)()
- expected = DataFrame(
- {"a": [1.0, 1.0], "b": [value, value], "c": [value, value]},
- index=[1, 2],
- )
- tm.assert_frame_equal(result, expected)
- def test_rolling_axis_one_with_nan():
- # GH: 35596
- df = DataFrame(
- [
- [0, 1, 2, 4, np.nan, np.nan, np.nan],
- [0, 1, 2, np.nan, np.nan, np.nan, np.nan],
- [0, 2, 2, np.nan, 2, np.nan, 1],
- ]
- )
- result = df.rolling(window=7, min_periods=1, axis="columns").sum()
- expected = DataFrame(
- [
- [0.0, 1.0, 3.0, 7.0, 7.0, 7.0, 7.0],
- [0.0, 1.0, 3.0, 3.0, 3.0, 3.0, 3.0],
- [0.0, 2.0, 4.0, 4.0, 6.0, 6.0, 7.0],
- ]
- )
- tm.assert_frame_equal(result, expected)
- @pytest.mark.parametrize(
- "value",
- ["test", to_datetime("2019-12-31"), to_timedelta("1 days 06:05:01.00003")],
- )
- def test_rolling_axis_1_non_numeric_dtypes(value):
- # GH: 20649
- df = DataFrame({"a": [1, 2]})
- df["b"] = value
- result = df.rolling(window=2, min_periods=1, axis=1).sum()
- expected = DataFrame({"a": [1.0, 2.0]})
- tm.assert_frame_equal(result, expected)
- def test_rolling_on_df_transposed():
- # GH: 32724
- df = DataFrame({"A": [1, None], "B": [4, 5], "C": [7, 8]})
- expected = DataFrame({"A": [1.0, np.nan], "B": [5.0, 5.0], "C": [11.0, 13.0]})
- result = df.rolling(min_periods=1, window=2, axis=1).sum()
- tm.assert_frame_equal(result, expected)
- result = df.T.rolling(min_periods=1, window=2).sum().T
- tm.assert_frame_equal(result, expected)
- @pytest.mark.parametrize(
- ("index", "window"),
- [
- (
- period_range(start="2020-01-01 08:00", end="2020-01-01 08:08", freq="T"),
- "2T",
- ),
- (
- period_range(start="2020-01-01 08:00", end="2020-01-01 12:00", freq="30T"),
- "1h",
- ),
- ],
- )
- @pytest.mark.parametrize(
- ("func", "values"),
- [
- ("min", [np.nan, 0, 0, 1, 2, 3, 4, 5, 6]),
- ("max", [np.nan, 0, 1, 2, 3, 4, 5, 6, 7]),
- ("sum", [np.nan, 0, 1, 3, 5, 7, 9, 11, 13]),
- ],
- )
- def test_rolling_period_index(index, window, func, values):
- # GH: 34225
- ds = Series([0, 1, 2, 3, 4, 5, 6, 7, 8], index=index)
- result = getattr(ds.rolling(window, closed="left"), func)()
- expected = Series(values, index=index)
- tm.assert_series_equal(result, expected)
- def test_rolling_sem(frame_or_series):
- # GH: 26476
- obj = frame_or_series([0, 1, 2])
- result = obj.rolling(2, min_periods=1).sem()
- if isinstance(result, DataFrame):
- result = Series(result[0].values)
- expected = Series([np.nan] + [0.7071067811865476] * 2)
- tm.assert_series_equal(result, expected)
- @pytest.mark.xfail(
- (is_platform_arm() and not is_platform_mac()) or is_platform_power(),
- reason="GH 38921",
- )
- @pytest.mark.parametrize(
- ("func", "third_value", "values"),
- [
- ("var", 1, [5e33, 0, 0.5, 0.5, 2, 0]),
- ("std", 1, [7.071068e16, 0, 0.7071068, 0.7071068, 1.414214, 0]),
- ("var", 2, [5e33, 0.5, 0, 0.5, 2, 0]),
- ("std", 2, [7.071068e16, 0.7071068, 0, 0.7071068, 1.414214, 0]),
- ],
- )
- def test_rolling_var_numerical_issues(func, third_value, values):
- # GH: 37051
- ds = Series([99999999999999999, 1, third_value, 2, 3, 1, 1])
- result = getattr(ds.rolling(2), func)()
- expected = Series([np.nan] + values)
- tm.assert_series_equal(result, expected)
- # GH 42064
- # new `roll_var` will output 0.0 correctly
- tm.assert_series_equal(result == 0, expected == 0)
- def test_timeoffset_as_window_parameter_for_corr():
- # GH: 28266
- exp = DataFrame(
- {
- "B": [
- np.nan,
- np.nan,
- 0.9999999999999998,
- -1.0,
- 1.0,
- -0.3273268353539892,
- 0.9999999999999998,
- 1.0,
- 0.9999999999999998,
- 1.0,
- ],
- "A": [
- np.nan,
- np.nan,
- -1.0,
- 1.0000000000000002,
- -0.3273268353539892,
- 0.9999999999999966,
- 1.0,
- 1.0000000000000002,
- 1.0,
- 1.0000000000000002,
- ],
- },
- index=MultiIndex.from_tuples(
- [
- (Timestamp("20130101 09:00:00"), "B"),
- (Timestamp("20130101 09:00:00"), "A"),
- (Timestamp("20130102 09:00:02"), "B"),
- (Timestamp("20130102 09:00:02"), "A"),
- (Timestamp("20130103 09:00:03"), "B"),
- (Timestamp("20130103 09:00:03"), "A"),
- (Timestamp("20130105 09:00:05"), "B"),
- (Timestamp("20130105 09:00:05"), "A"),
- (Timestamp("20130106 09:00:06"), "B"),
- (Timestamp("20130106 09:00:06"), "A"),
- ]
- ),
- )
- df = DataFrame(
- {"B": [0, 1, 2, 4, 3], "A": [7, 4, 6, 9, 3]},
- index=[
- Timestamp("20130101 09:00:00"),
- Timestamp("20130102 09:00:02"),
- Timestamp("20130103 09:00:03"),
- Timestamp("20130105 09:00:05"),
- Timestamp("20130106 09:00:06"),
- ],
- )
- res = df.rolling(window="3d").corr()
- tm.assert_frame_equal(exp, res)
- @pytest.mark.parametrize("method", ["var", "sum", "mean", "skew", "kurt", "min", "max"])
- def test_rolling_decreasing_indices(method):
- """
- Make sure that decreasing indices give the same results as increasing indices.
- GH 36933
- """
- df = DataFrame({"values": np.arange(-15, 10) ** 2})
- df_reverse = DataFrame({"values": df["values"][::-1]}, index=df.index[::-1])
- increasing = getattr(df.rolling(window=5), method)()
- decreasing = getattr(df_reverse.rolling(window=5), method)()
- assert np.abs(decreasing.values[::-1][:-4] - increasing.values[4:]).max() < 1e-12
- @pytest.mark.parametrize(
- "window,closed,expected",
- [
- ("2s", "right", [1.0, 3.0, 5.0, 3.0]),
- ("2s", "left", [0.0, 1.0, 3.0, 5.0]),
- ("2s", "both", [1.0, 3.0, 6.0, 5.0]),
- ("2s", "neither", [0.0, 1.0, 2.0, 3.0]),
- ("3s", "right", [1.0, 3.0, 6.0, 5.0]),
- ("3s", "left", [1.0, 3.0, 6.0, 5.0]),
- ("3s", "both", [1.0, 3.0, 6.0, 5.0]),
- ("3s", "neither", [1.0, 3.0, 6.0, 5.0]),
- ],
- )
- def test_rolling_decreasing_indices_centered(window, closed, expected, frame_or_series):
- """
- Ensure that a symmetrical inverted index return same result as non-inverted.
- """
- # GH 43927
- index = date_range("2020", periods=4, freq="1s")
- df_inc = frame_or_series(range(4), index=index)
- df_dec = frame_or_series(range(4), index=index[::-1])
- expected_inc = frame_or_series(expected, index=index)
- expected_dec = frame_or_series(expected, index=index[::-1])
- result_inc = df_inc.rolling(window, closed=closed, center=True).sum()
- result_dec = df_dec.rolling(window, closed=closed, center=True).sum()
- tm.assert_equal(result_inc, expected_inc)
- tm.assert_equal(result_dec, expected_dec)
- @pytest.mark.parametrize(
- "window,expected",
- [
- ("1ns", [1.0, 1.0, 1.0, 1.0]),
- ("3ns", [2.0, 3.0, 3.0, 2.0]),
- ],
- )
- def test_rolling_center_nanosecond_resolution(
- window, closed, expected, frame_or_series
- ):
- index = date_range("2020", periods=4, freq="1ns")
- df = frame_or_series([1, 1, 1, 1], index=index, dtype=float)
- expected = frame_or_series(expected, index=index, dtype=float)
- result = df.rolling(window, closed=closed, center=True).sum()
- tm.assert_equal(result, expected)
- @pytest.mark.parametrize(
- "method,expected",
- [
- (
- "var",
- [
- float("nan"),
- 43.0,
- float("nan"),
- 136.333333,
- 43.5,
- 94.966667,
- 182.0,
- 318.0,
- ],
- ),
- (
- "mean",
- [float("nan"), 7.5, float("nan"), 21.5, 6.0, 9.166667, 13.0, 17.5],
- ),
- (
- "sum",
- [float("nan"), 30.0, float("nan"), 86.0, 30.0, 55.0, 91.0, 140.0],
- ),
- (
- "skew",
- [
- float("nan"),
- 0.709296,
- float("nan"),
- 0.407073,
- 0.984656,
- 0.919184,
- 0.874674,
- 0.842418,
- ],
- ),
- (
- "kurt",
- [
- float("nan"),
- -0.5916711736073559,
- float("nan"),
- -1.0028993131317954,
- -0.06103844629409494,
- -0.254143227116194,
- -0.37362637362637585,
- -0.45439658241367054,
- ],
- ),
- ],
- )
- def test_rolling_non_monotonic(method, expected):
- """
- Make sure the (rare) branch of non-monotonic indices is covered by a test.
- output from 1.1.3 is assumed to be the expected output. Output of sum/mean has
- manually been verified.
- GH 36933.
- """
- # Based on an example found in computation.rst
- use_expanding = [True, False, True, False, True, True, True, True]
- df = DataFrame({"values": np.arange(len(use_expanding)) ** 2})
- class CustomIndexer(BaseIndexer):
- def get_window_bounds(self, num_values, min_periods, center, closed, step):
- start = np.empty(num_values, dtype=np.int64)
- end = np.empty(num_values, dtype=np.int64)
- for i in range(num_values):
- if self.use_expanding[i]:
- start[i] = 0
- end[i] = i + 1
- else:
- start[i] = i
- end[i] = i + self.window_size
- return start, end
- indexer = CustomIndexer(window_size=4, use_expanding=use_expanding)
- result = getattr(df.rolling(indexer), method)()
- expected = DataFrame({"values": expected})
- tm.assert_frame_equal(result, expected)
- @pytest.mark.parametrize(
- ("index", "window"),
- [
- ([0, 1, 2, 3, 4], 2),
- (date_range("2001-01-01", freq="D", periods=5), "2D"),
- ],
- )
- def test_rolling_corr_timedelta_index(index, window):
- # GH: 31286
- x = Series([1, 2, 3, 4, 5], index=index)
- y = x.copy()
- x.iloc[0:2] = 0.0
- result = x.rolling(window).corr(y)
- expected = Series([np.nan, np.nan, 1, 1, 1], index=index)
- tm.assert_almost_equal(result, expected)
- def test_groupby_rolling_nan_included():
- # GH 35542
- data = {"group": ["g1", np.nan, "g1", "g2", np.nan], "B": [0, 1, 2, 3, 4]}
- df = DataFrame(data)
- result = df.groupby("group", dropna=False).rolling(1, min_periods=1).mean()
- expected = DataFrame(
- {"B": [0.0, 2.0, 3.0, 1.0, 4.0]},
- # GH-38057 from_tuples puts the NaNs in the codes, result expects them
- # to be in the levels, at the moment
- # index=MultiIndex.from_tuples(
- # [("g1", 0), ("g1", 2), ("g2", 3), (np.nan, 1), (np.nan, 4)],
- # names=["group", None],
- # ),
- index=MultiIndex(
- [["g1", "g2", np.nan], [0, 1, 2, 3, 4]],
- [[0, 0, 1, 2, 2], [0, 2, 3, 1, 4]],
- names=["group", None],
- ),
- )
- tm.assert_frame_equal(result, expected)
- @pytest.mark.parametrize("method", ["skew", "kurt"])
- def test_rolling_skew_kurt_numerical_stability(method):
- # GH#6929
- ser = Series(np.random.rand(10))
- ser_copy = ser.copy()
- expected = getattr(ser.rolling(3), method)()
- tm.assert_series_equal(ser, ser_copy)
- ser = ser + 50000
- result = getattr(ser.rolling(3), method)()
- tm.assert_series_equal(result, expected)
- @pytest.mark.parametrize(
- ("method", "values"),
- [
- ("skew", [2.0, 0.854563, 0.0, 1.999984]),
- ("kurt", [4.0, -1.289256, -1.2, 3.999946]),
- ],
- )
- def test_rolling_skew_kurt_large_value_range(method, values):
- # GH: 37557
- s = Series([3000000, 1, 1, 2, 3, 4, 999])
- result = getattr(s.rolling(4), method)()
- expected = Series([np.nan] * 3 + values)
- tm.assert_series_equal(result, expected)
- def test_invalid_method():
- with pytest.raises(ValueError, match="method must be 'table' or 'single"):
- Series(range(1)).rolling(1, method="foo")
- @pytest.mark.parametrize("window", [1, "1d"])
- def test_rolling_descending_date_order_with_offset(window, frame_or_series):
- # GH#40002
- idx = date_range(start="2020-01-01", end="2020-01-03", freq="1d")
- obj = frame_or_series(range(1, 4), index=idx)
- result = obj.rolling("1d", closed="left").sum()
- expected = frame_or_series([np.nan, 1, 2], index=idx)
- tm.assert_equal(result, expected)
- result = obj.iloc[::-1].rolling("1d", closed="left").sum()
- idx = date_range(start="2020-01-03", end="2020-01-01", freq="-1d")
- expected = frame_or_series([np.nan, 3, 2], index=idx)
- tm.assert_equal(result, expected)
- def test_rolling_var_floating_artifact_precision():
- # GH 37051
- s = Series([7, 5, 5, 5])
- result = s.rolling(3).var()
- expected = Series([np.nan, np.nan, 4 / 3, 0])
- tm.assert_series_equal(result, expected, atol=1.0e-15, rtol=1.0e-15)
- # GH 42064
- # new `roll_var` will output 0.0 correctly
- tm.assert_series_equal(result == 0, expected == 0)
- def test_rolling_std_small_values():
- # GH 37051
- s = Series(
- [
- 0.00000054,
- 0.00000053,
- 0.00000054,
- ]
- )
- result = s.rolling(2).std()
- expected = Series([np.nan, 7.071068e-9, 7.071068e-9])
- tm.assert_series_equal(result, expected, atol=1.0e-15, rtol=1.0e-15)
- @pytest.mark.parametrize(
- "start, exp_values",
- [
- (1, [0.03, 0.0155, 0.0155, 0.011, 0.01025]),
- (2, [0.001, 0.001, 0.0015, 0.00366666]),
- ],
- )
- def test_rolling_mean_all_nan_window_floating_artifacts(start, exp_values):
- # GH#41053
- df = DataFrame(
- [
- 0.03,
- 0.03,
- 0.001,
- np.NaN,
- 0.002,
- 0.008,
- np.NaN,
- np.NaN,
- np.NaN,
- np.NaN,
- np.NaN,
- np.NaN,
- 0.005,
- 0.2,
- ]
- )
- values = exp_values + [
- 0.00366666,
- 0.005,
- 0.005,
- 0.008,
- np.NaN,
- np.NaN,
- 0.005,
- 0.102500,
- ]
- expected = DataFrame(
- values,
- index=list(range(start, len(values) + start)),
- )
- result = df.iloc[start:].rolling(5, min_periods=0).mean()
- tm.assert_frame_equal(result, expected)
- def test_rolling_sum_all_nan_window_floating_artifacts():
- # GH#41053
- df = DataFrame([0.002, 0.008, 0.005, np.NaN, np.NaN, np.NaN])
- result = df.rolling(3, min_periods=0).sum()
- expected = DataFrame([0.002, 0.010, 0.015, 0.013, 0.005, 0.0])
- tm.assert_frame_equal(result, expected)
- def test_rolling_zero_window():
- # GH 22719
- s = Series(range(1))
- result = s.rolling(0).min()
- expected = Series([np.nan])
- tm.assert_series_equal(result, expected)
- def test_rolling_float_dtype(float_numpy_dtype):
- # GH#42452
- df = DataFrame({"A": range(5), "B": range(10, 15)}, dtype=float_numpy_dtype)
- expected = DataFrame(
- {"A": [np.nan] * 5, "B": range(10, 20, 2)},
- dtype=float_numpy_dtype,
- )
- result = df.rolling(2, axis=1).sum()
- tm.assert_frame_equal(result, expected, check_dtype=False)
- def test_rolling_numeric_dtypes():
- # GH#41779
- df = DataFrame(np.arange(40).reshape(4, 10), columns=list("abcdefghij")).astype(
- {
- "a": "float16",
- "b": "float32",
- "c": "float64",
- "d": "int8",
- "e": "int16",
- "f": "int32",
- "g": "uint8",
- "h": "uint16",
- "i": "uint32",
- "j": "uint64",
- }
- )
- result = df.rolling(window=2, min_periods=1, axis=1).min()
- expected = DataFrame(
- {
- "a": range(0, 40, 10),
- "b": range(0, 40, 10),
- "c": range(1, 40, 10),
- "d": range(2, 40, 10),
- "e": range(3, 40, 10),
- "f": range(4, 40, 10),
- "g": range(5, 40, 10),
- "h": range(6, 40, 10),
- "i": range(7, 40, 10),
- "j": range(8, 40, 10),
- },
- dtype="float64",
- )
- tm.assert_frame_equal(result, expected)
- @pytest.mark.parametrize("window", [1, 3, 10, 20])
- @pytest.mark.parametrize("method", ["min", "max", "average"])
- @pytest.mark.parametrize("pct", [True, False])
- @pytest.mark.parametrize("ascending", [True, False])
- @pytest.mark.parametrize("test_data", ["default", "duplicates", "nans"])
- def test_rank(window, method, pct, ascending, test_data):
- length = 20
- if test_data == "default":
- ser = Series(data=np.random.rand(length))
- elif test_data == "duplicates":
- ser = Series(data=np.random.choice(3, length))
- elif test_data == "nans":
- ser = Series(
- data=np.random.choice([1.0, 0.25, 0.75, np.nan, np.inf, -np.inf], length)
- )
- expected = ser.rolling(window).apply(
- lambda x: x.rank(method=method, pct=pct, ascending=ascending).iloc[-1]
- )
- result = ser.rolling(window).rank(method=method, pct=pct, ascending=ascending)
- tm.assert_series_equal(result, expected)
- def test_rolling_quantile_np_percentile():
- # #9413: Tests that rolling window's quantile default behavior
- # is analogous to Numpy's percentile
- row = 10
- col = 5
- idx = date_range("20100101", periods=row, freq="B")
- df = DataFrame(np.random.rand(row * col).reshape((row, -1)), index=idx)
- df_quantile = df.quantile([0.25, 0.5, 0.75], axis=0)
- np_percentile = np.percentile(df, [25, 50, 75], axis=0)
- tm.assert_almost_equal(df_quantile.values, np.array(np_percentile))
- @pytest.mark.parametrize("quantile", [0.0, 0.1, 0.45, 0.5, 1])
- @pytest.mark.parametrize(
- "interpolation", ["linear", "lower", "higher", "nearest", "midpoint"]
- )
- @pytest.mark.parametrize(
- "data",
- [
- [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0],
- [8.0, 1.0, 3.0, 4.0, 5.0, 2.0, 6.0, 7.0],
- [0.0, np.nan, 0.2, np.nan, 0.4],
- [np.nan, np.nan, np.nan, np.nan],
- [np.nan, 0.1, np.nan, 0.3, 0.4, 0.5],
- [0.5],
- [np.nan, 0.7, 0.6],
- ],
- )
- def test_rolling_quantile_interpolation_options(quantile, interpolation, data):
- # Tests that rolling window's quantile behavior is analogous to
- # Series' quantile for each interpolation option
- s = Series(data)
- q1 = s.quantile(quantile, interpolation)
- q2 = s.expanding(min_periods=1).quantile(quantile, interpolation).iloc[-1]
- if np.isnan(q1):
- assert np.isnan(q2)
- else:
- assert q1 == q2
- def test_invalid_quantile_value():
- data = np.arange(5)
- s = Series(data)
- msg = "Interpolation 'invalid' is not supported"
- with pytest.raises(ValueError, match=msg):
- s.rolling(len(data), min_periods=1).quantile(0.5, interpolation="invalid")
- def test_rolling_quantile_param():
- ser = Series([0.0, 0.1, 0.5, 0.9, 1.0])
- msg = "quantile value -0.1 not in \\[0, 1\\]"
- with pytest.raises(ValueError, match=msg):
- ser.rolling(3).quantile(-0.1)
- msg = "quantile value 10.0 not in \\[0, 1\\]"
- with pytest.raises(ValueError, match=msg):
- ser.rolling(3).quantile(10.0)
- msg = "must be real number, not str"
- with pytest.raises(TypeError, match=msg):
- ser.rolling(3).quantile("foo")
- def test_rolling_std_1obs():
- vals = Series([1.0, 2.0, 3.0, 4.0, 5.0])
- result = vals.rolling(1, min_periods=1).std()
- expected = Series([np.nan] * 5)
- tm.assert_series_equal(result, expected)
- result = vals.rolling(1, min_periods=1).std(ddof=0)
- expected = Series([0.0] * 5)
- tm.assert_series_equal(result, expected)
- result = Series([np.nan, np.nan, 3, 4, 5]).rolling(3, min_periods=2).std()
- assert np.isnan(result[2])
- def test_rolling_std_neg_sqrt():
- # unit test from Bottleneck
- # Test move_nanstd for neg sqrt.
- a = Series(
- [
- 0.0011448196318903589,
- 0.00028718669878572767,
- 0.00028718669878572767,
- 0.00028718669878572767,
- 0.00028718669878572767,
- ]
- )
- b = a.rolling(window=3).std()
- assert np.isfinite(b[2:]).all()
- b = a.ewm(span=3).std()
- assert np.isfinite(b[2:]).all()
- def test_step_not_integer_raises():
- with pytest.raises(ValueError, match="step must be an integer"):
- DataFrame(range(2)).rolling(1, step="foo")
- def test_step_not_positive_raises():
- with pytest.raises(ValueError, match="step must be >= 0"):
- DataFrame(range(2)).rolling(1, step=-1)
- @pytest.mark.parametrize(
- ["values", "window", "min_periods", "expected"],
- [
- [
- [20, 10, 10, np.inf, 1, 1, 2, 3],
- 3,
- 1,
- [np.nan, 50, 100 / 3, 0, 40.5, 0, 1 / 3, 1],
- ],
- [
- [20, 10, 10, np.nan, 10, 1, 2, 3],
- 3,
- 1,
- [np.nan, 50, 100 / 3, 0, 0, 40.5, 73 / 3, 1],
- ],
- [
- [np.nan, 5, 6, 7, 5, 5, 5],
- 3,
- 3,
- [np.nan] * 3 + [1, 1, 4 / 3, 0],
- ],
- [
- [5, 7, 7, 7, np.nan, np.inf, 4, 3, 3, 3],
- 3,
- 3,
- [np.nan] * 2 + [4 / 3, 0] + [np.nan] * 4 + [1 / 3, 0],
- ],
- [
- [5, 7, 7, 7, np.nan, np.inf, 7, 3, 3, 3],
- 3,
- 3,
- [np.nan] * 2 + [4 / 3, 0] + [np.nan] * 4 + [16 / 3, 0],
- ],
- [
- [5, 7] * 4,
- 3,
- 3,
- [np.nan] * 2 + [4 / 3] * 6,
- ],
- [
- [5, 7, 5, np.nan, 7, 5, 7],
- 3,
- 2,
- [np.nan, 2, 4 / 3] + [2] * 3 + [4 / 3],
- ],
- ],
- )
- def test_rolling_var_same_value_count_logic(values, window, min_periods, expected):
- # GH 42064.
- expected = Series(expected)
- sr = Series(values)
- # With new algo implemented, result will be set to .0 in rolling var
- # if sufficient amount of consecutively same values are found.
- result_var = sr.rolling(window, min_periods=min_periods).var()
- # use `assert_series_equal` twice to check for equality,
- # because `check_exact=True` will fail in 32-bit tests due to
- # precision loss.
- # 1. result should be close to correct value
- # non-zero values can still differ slightly from "truth"
- # as the result of online algorithm
- tm.assert_series_equal(result_var, expected)
- # 2. zeros should be exactly the same since the new algo takes effect here
- tm.assert_series_equal(expected == 0, result_var == 0)
- # std should also pass as it's just a sqrt of var
- result_std = sr.rolling(window, min_periods=min_periods).std()
- tm.assert_series_equal(result_std, np.sqrt(expected))
- tm.assert_series_equal(expected == 0, result_std == 0)
- def test_rolling_mean_sum_floating_artifacts():
- # GH 42064.
- sr = Series([1 / 3, 4, 0, 0, 0, 0, 0])
- r = sr.rolling(3)
- result = r.mean()
- assert (result[-3:] == 0).all()
- result = r.sum()
- assert (result[-3:] == 0).all()
- def test_rolling_skew_kurt_floating_artifacts():
- # GH 42064 46431
- sr = Series([1 / 3, 4, 0, 0, 0, 0, 0])
- r = sr.rolling(4)
- result = r.skew()
- assert (result[-2:] == 0).all()
- result = r.kurt()
- assert (result[-2:] == -3).all()
- def test_numeric_only_frame(arithmetic_win_operators, numeric_only):
- # GH#46560
- kernel = arithmetic_win_operators
- df = DataFrame({"a": [1], "b": 2, "c": 3})
- df["c"] = df["c"].astype(object)
- rolling = df.rolling(2, min_periods=1)
- op = getattr(rolling, kernel)
- result = op(numeric_only=numeric_only)
- columns = ["a", "b"] if numeric_only else ["a", "b", "c"]
- expected = df[columns].agg([kernel]).reset_index(drop=True).astype(float)
- assert list(expected.columns) == columns
- tm.assert_frame_equal(result, expected)
- @pytest.mark.parametrize("kernel", ["corr", "cov"])
- @pytest.mark.parametrize("use_arg", [True, False])
- def test_numeric_only_corr_cov_frame(kernel, numeric_only, use_arg):
- # GH#46560
- df = DataFrame({"a": [1, 2, 3], "b": 2, "c": 3})
- df["c"] = df["c"].astype(object)
- arg = (df,) if use_arg else ()
- rolling = df.rolling(2, min_periods=1)
- op = getattr(rolling, kernel)
- result = op(*arg, numeric_only=numeric_only)
- # Compare result to op using float dtypes, dropping c when numeric_only is True
- columns = ["a", "b"] if numeric_only else ["a", "b", "c"]
- df2 = df[columns].astype(float)
- arg2 = (df2,) if use_arg else ()
- rolling2 = df2.rolling(2, min_periods=1)
- op2 = getattr(rolling2, kernel)
- expected = op2(*arg2, numeric_only=numeric_only)
- tm.assert_frame_equal(result, expected)
- @pytest.mark.parametrize("dtype", [int, object])
- def test_numeric_only_series(arithmetic_win_operators, numeric_only, dtype):
- # GH#46560
- kernel = arithmetic_win_operators
- ser = Series([1], dtype=dtype)
- rolling = ser.rolling(2, min_periods=1)
- op = getattr(rolling, kernel)
- if numeric_only and dtype is object:
- msg = f"Rolling.{kernel} does not implement numeric_only"
- with pytest.raises(NotImplementedError, match=msg):
- op(numeric_only=numeric_only)
- else:
- result = op(numeric_only=numeric_only)
- expected = ser.agg([kernel]).reset_index(drop=True).astype(float)
- tm.assert_series_equal(result, expected)
- @pytest.mark.parametrize("kernel", ["corr", "cov"])
- @pytest.mark.parametrize("use_arg", [True, False])
- @pytest.mark.parametrize("dtype", [int, object])
- def test_numeric_only_corr_cov_series(kernel, use_arg, numeric_only, dtype):
- # GH#46560
- ser = Series([1, 2, 3], dtype=dtype)
- arg = (ser,) if use_arg else ()
- rolling = ser.rolling(2, min_periods=1)
- op = getattr(rolling, kernel)
- if numeric_only and dtype is object:
- msg = f"Rolling.{kernel} does not implement numeric_only"
- with pytest.raises(NotImplementedError, match=msg):
- op(*arg, numeric_only=numeric_only)
- else:
- result = op(*arg, numeric_only=numeric_only)
- ser2 = ser.astype(float)
- arg2 = (ser2,) if use_arg else ()
- rolling2 = ser2.rolling(2, min_periods=1)
- op2 = getattr(rolling2, kernel)
- expected = op2(*arg2, numeric_only=numeric_only)
- tm.assert_series_equal(result, expected)
|