test_rolling.py 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935
  1. from datetime import (
  2. datetime,
  3. timedelta,
  4. )
  5. import numpy as np
  6. import pytest
  7. from pandas.compat import (
  8. is_platform_arm,
  9. is_platform_mac,
  10. is_platform_power,
  11. )
  12. from pandas import (
  13. DataFrame,
  14. DatetimeIndex,
  15. MultiIndex,
  16. Series,
  17. Timedelta,
  18. Timestamp,
  19. date_range,
  20. period_range,
  21. to_datetime,
  22. to_timedelta,
  23. )
  24. import pandas._testing as tm
  25. from pandas.api.indexers import BaseIndexer
  26. from pandas.core.indexers.objects import VariableOffsetWindowIndexer
  27. from pandas.tseries.offsets import BusinessDay
  28. def test_doc_string():
  29. df = DataFrame({"B": [0, 1, 2, np.nan, 4]})
  30. df
  31. df.rolling(2).sum()
  32. df.rolling(2, min_periods=1).sum()
  33. def test_constructor(frame_or_series):
  34. # GH 12669
  35. c = frame_or_series(range(5)).rolling
  36. # valid
  37. c(0)
  38. c(window=2)
  39. c(window=2, min_periods=1)
  40. c(window=2, min_periods=1, center=True)
  41. c(window=2, min_periods=1, center=False)
  42. # GH 13383
  43. msg = "window must be an integer 0 or greater"
  44. with pytest.raises(ValueError, match=msg):
  45. c(-1)
  46. @pytest.mark.parametrize("w", [2.0, "foo", np.array([2])])
  47. def test_invalid_constructor(frame_or_series, w):
  48. # not valid
  49. c = frame_or_series(range(5)).rolling
  50. msg = "|".join(
  51. [
  52. "window must be an integer",
  53. "passed window foo is not compatible with a datetimelike index",
  54. ]
  55. )
  56. with pytest.raises(ValueError, match=msg):
  57. c(window=w)
  58. msg = "min_periods must be an integer"
  59. with pytest.raises(ValueError, match=msg):
  60. c(window=2, min_periods=w)
  61. msg = "center must be a boolean"
  62. with pytest.raises(ValueError, match=msg):
  63. c(window=2, min_periods=1, center=w)
  64. @pytest.mark.parametrize(
  65. "window",
  66. [
  67. timedelta(days=3),
  68. Timedelta(days=3),
  69. "3D",
  70. VariableOffsetWindowIndexer(
  71. index=date_range("2015-12-25", periods=5), offset=BusinessDay(1)
  72. ),
  73. ],
  74. )
  75. def test_freq_window_not_implemented(window):
  76. # GH 15354
  77. df = DataFrame(
  78. np.arange(10),
  79. index=date_range("2015-12-24", periods=10, freq="D"),
  80. )
  81. with pytest.raises(
  82. NotImplementedError, match="step is not supported with frequency windows"
  83. ):
  84. df.rolling("3D", step=3)
  85. @pytest.mark.parametrize("agg", ["cov", "corr"])
  86. def test_step_not_implemented_for_cov_corr(agg):
  87. # GH 15354
  88. roll = DataFrame(range(2)).rolling(1, step=2)
  89. with pytest.raises(NotImplementedError, match="step not implemented"):
  90. getattr(roll, agg)()
  91. @pytest.mark.parametrize("window", [timedelta(days=3), Timedelta(days=3)])
  92. def test_constructor_with_timedelta_window(window):
  93. # GH 15440
  94. n = 10
  95. df = DataFrame(
  96. {"value": np.arange(n)},
  97. index=date_range("2015-12-24", periods=n, freq="D"),
  98. )
  99. expected_data = np.append([0.0, 1.0], np.arange(3.0, 27.0, 3))
  100. result = df.rolling(window=window).sum()
  101. expected = DataFrame(
  102. {"value": expected_data},
  103. index=date_range("2015-12-24", periods=n, freq="D"),
  104. )
  105. tm.assert_frame_equal(result, expected)
  106. expected = df.rolling("3D").sum()
  107. tm.assert_frame_equal(result, expected)
  108. @pytest.mark.parametrize("window", [timedelta(days=3), Timedelta(days=3), "3D"])
  109. def test_constructor_timedelta_window_and_minperiods(window, raw):
  110. # GH 15305
  111. n = 10
  112. df = DataFrame(
  113. {"value": np.arange(n)},
  114. index=date_range("2017-08-08", periods=n, freq="D"),
  115. )
  116. expected = DataFrame(
  117. {"value": np.append([np.NaN, 1.0], np.arange(3.0, 27.0, 3))},
  118. index=date_range("2017-08-08", periods=n, freq="D"),
  119. )
  120. result_roll_sum = df.rolling(window=window, min_periods=2).sum()
  121. result_roll_generic = df.rolling(window=window, min_periods=2).apply(sum, raw=raw)
  122. tm.assert_frame_equal(result_roll_sum, expected)
  123. tm.assert_frame_equal(result_roll_generic, expected)
  124. def test_closed_fixed(closed, arithmetic_win_operators):
  125. # GH 34315
  126. func_name = arithmetic_win_operators
  127. df_fixed = DataFrame({"A": [0, 1, 2, 3, 4]})
  128. df_time = DataFrame({"A": [0, 1, 2, 3, 4]}, index=date_range("2020", periods=5))
  129. result = getattr(
  130. df_fixed.rolling(2, closed=closed, min_periods=1),
  131. func_name,
  132. )()
  133. expected = getattr(
  134. df_time.rolling("2D", closed=closed, min_periods=1),
  135. func_name,
  136. )().reset_index(drop=True)
  137. tm.assert_frame_equal(result, expected)
  138. @pytest.mark.parametrize(
  139. "closed, window_selections",
  140. [
  141. (
  142. "both",
  143. [
  144. [True, True, False, False, False],
  145. [True, True, True, False, False],
  146. [False, True, True, True, False],
  147. [False, False, True, True, True],
  148. [False, False, False, True, True],
  149. ],
  150. ),
  151. (
  152. "left",
  153. [
  154. [True, False, False, False, False],
  155. [True, True, False, False, False],
  156. [False, True, True, False, False],
  157. [False, False, True, True, False],
  158. [False, False, False, True, True],
  159. ],
  160. ),
  161. (
  162. "right",
  163. [
  164. [True, True, False, False, False],
  165. [False, True, True, False, False],
  166. [False, False, True, True, False],
  167. [False, False, False, True, True],
  168. [False, False, False, False, True],
  169. ],
  170. ),
  171. (
  172. "neither",
  173. [
  174. [True, False, False, False, False],
  175. [False, True, False, False, False],
  176. [False, False, True, False, False],
  177. [False, False, False, True, False],
  178. [False, False, False, False, True],
  179. ],
  180. ),
  181. ],
  182. )
  183. def test_datetimelike_centered_selections(
  184. closed, window_selections, arithmetic_win_operators
  185. ):
  186. # GH 34315
  187. func_name = arithmetic_win_operators
  188. df_time = DataFrame(
  189. {"A": [0.0, 1.0, 2.0, 3.0, 4.0]}, index=date_range("2020", periods=5)
  190. )
  191. expected = DataFrame(
  192. {"A": [getattr(df_time["A"].iloc[s], func_name)() for s in window_selections]},
  193. index=date_range("2020", periods=5),
  194. )
  195. if func_name == "sem":
  196. kwargs = {"ddof": 0}
  197. else:
  198. kwargs = {}
  199. result = getattr(
  200. df_time.rolling("2D", closed=closed, min_periods=1, center=True),
  201. func_name,
  202. )(**kwargs)
  203. tm.assert_frame_equal(result, expected, check_dtype=False)
  204. @pytest.mark.parametrize(
  205. "window,closed,expected",
  206. [
  207. ("3s", "right", [3.0, 3.0, 3.0]),
  208. ("3s", "both", [3.0, 3.0, 3.0]),
  209. ("3s", "left", [3.0, 3.0, 3.0]),
  210. ("3s", "neither", [3.0, 3.0, 3.0]),
  211. ("2s", "right", [3.0, 2.0, 2.0]),
  212. ("2s", "both", [3.0, 3.0, 3.0]),
  213. ("2s", "left", [1.0, 3.0, 3.0]),
  214. ("2s", "neither", [1.0, 2.0, 2.0]),
  215. ],
  216. )
  217. def test_datetimelike_centered_offset_covers_all(
  218. window, closed, expected, frame_or_series
  219. ):
  220. # GH 42753
  221. index = [
  222. Timestamp("20130101 09:00:01"),
  223. Timestamp("20130101 09:00:02"),
  224. Timestamp("20130101 09:00:02"),
  225. ]
  226. df = frame_or_series([1, 1, 1], index=index)
  227. result = df.rolling(window, closed=closed, center=True).sum()
  228. expected = frame_or_series(expected, index=index)
  229. tm.assert_equal(result, expected)
  230. @pytest.mark.parametrize(
  231. "window,closed,expected",
  232. [
  233. ("2D", "right", [4, 4, 4, 4, 4, 4, 2, 2]),
  234. ("2D", "left", [2, 2, 4, 4, 4, 4, 4, 4]),
  235. ("2D", "both", [4, 4, 6, 6, 6, 6, 4, 4]),
  236. ("2D", "neither", [2, 2, 2, 2, 2, 2, 2, 2]),
  237. ],
  238. )
  239. def test_datetimelike_nonunique_index_centering(
  240. window, closed, expected, frame_or_series
  241. ):
  242. index = DatetimeIndex(
  243. [
  244. "2020-01-01",
  245. "2020-01-01",
  246. "2020-01-02",
  247. "2020-01-02",
  248. "2020-01-03",
  249. "2020-01-03",
  250. "2020-01-04",
  251. "2020-01-04",
  252. ]
  253. )
  254. df = frame_or_series([1] * 8, index=index, dtype=float)
  255. expected = frame_or_series(expected, index=index, dtype=float)
  256. result = df.rolling(window, center=True, closed=closed).sum()
  257. tm.assert_equal(result, expected)
  258. def test_even_number_window_alignment():
  259. # see discussion in GH 38780
  260. s = Series(range(3), index=date_range(start="2020-01-01", freq="D", periods=3))
  261. # behavior of index- and datetime-based windows differs here!
  262. # s.rolling(window=2, min_periods=1, center=True).mean()
  263. result = s.rolling(window="2D", min_periods=1, center=True).mean()
  264. expected = Series([0.5, 1.5, 2], index=s.index)
  265. tm.assert_series_equal(result, expected)
  266. def test_closed_fixed_binary_col(center, step):
  267. # GH 34315
  268. data = [0, 1, 1, 0, 0, 1, 0, 1]
  269. df = DataFrame(
  270. {"binary_col": data},
  271. index=date_range(start="2020-01-01", freq="min", periods=len(data)),
  272. )
  273. if center:
  274. expected_data = [2 / 3, 0.5, 0.4, 0.5, 0.428571, 0.5, 0.571429, 0.5]
  275. else:
  276. expected_data = [np.nan, 0, 0.5, 2 / 3, 0.5, 0.4, 0.5, 0.428571]
  277. expected = DataFrame(
  278. expected_data,
  279. columns=["binary_col"],
  280. index=date_range(start="2020-01-01", freq="min", periods=len(expected_data)),
  281. )[::step]
  282. rolling = df.rolling(
  283. window=len(df), closed="left", min_periods=1, center=center, step=step
  284. )
  285. result = rolling.mean()
  286. tm.assert_frame_equal(result, expected)
  287. @pytest.mark.parametrize("closed", ["neither", "left"])
  288. def test_closed_empty(closed, arithmetic_win_operators):
  289. # GH 26005
  290. func_name = arithmetic_win_operators
  291. ser = Series(data=np.arange(5), index=date_range("2000", periods=5, freq="2D"))
  292. roll = ser.rolling("1D", closed=closed)
  293. result = getattr(roll, func_name)()
  294. expected = Series([np.nan] * 5, index=ser.index)
  295. tm.assert_series_equal(result, expected)
  296. @pytest.mark.parametrize("func", ["min", "max"])
  297. def test_closed_one_entry(func):
  298. # GH24718
  299. ser = Series(data=[2], index=date_range("2000", periods=1))
  300. result = getattr(ser.rolling("10D", closed="left"), func)()
  301. tm.assert_series_equal(result, Series([np.nan], index=ser.index))
  302. @pytest.mark.parametrize("func", ["min", "max"])
  303. def test_closed_one_entry_groupby(func):
  304. # GH24718
  305. ser = DataFrame(
  306. data={"A": [1, 1, 2], "B": [3, 2, 1]},
  307. index=date_range("2000", periods=3),
  308. )
  309. result = getattr(
  310. ser.groupby("A", sort=False)["B"].rolling("10D", closed="left"), func
  311. )()
  312. exp_idx = MultiIndex.from_arrays(arrays=[[1, 1, 2], ser.index], names=("A", None))
  313. expected = Series(data=[np.nan, 3, np.nan], index=exp_idx, name="B")
  314. tm.assert_series_equal(result, expected)
  315. @pytest.mark.parametrize("input_dtype", ["int", "float"])
  316. @pytest.mark.parametrize(
  317. "func,closed,expected",
  318. [
  319. ("min", "right", [0.0, 0, 0, 1, 2, 3, 4, 5, 6, 7]),
  320. ("min", "both", [0.0, 0, 0, 0, 1, 2, 3, 4, 5, 6]),
  321. ("min", "neither", [np.nan, 0, 0, 1, 2, 3, 4, 5, 6, 7]),
  322. ("min", "left", [np.nan, 0, 0, 0, 1, 2, 3, 4, 5, 6]),
  323. ("max", "right", [0.0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
  324. ("max", "both", [0.0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
  325. ("max", "neither", [np.nan, 0, 1, 2, 3, 4, 5, 6, 7, 8]),
  326. ("max", "left", [np.nan, 0, 1, 2, 3, 4, 5, 6, 7, 8]),
  327. ],
  328. )
  329. def test_closed_min_max_datetime(input_dtype, func, closed, expected):
  330. # see gh-21704
  331. ser = Series(
  332. data=np.arange(10).astype(input_dtype),
  333. index=date_range("2000", periods=10),
  334. )
  335. result = getattr(ser.rolling("3D", closed=closed), func)()
  336. expected = Series(expected, index=ser.index)
  337. tm.assert_series_equal(result, expected)
  338. def test_closed_uneven():
  339. # see gh-21704
  340. ser = Series(data=np.arange(10), index=date_range("2000", periods=10))
  341. # uneven
  342. ser = ser.drop(index=ser.index[[1, 5]])
  343. result = ser.rolling("3D", closed="left").min()
  344. expected = Series([np.nan, 0, 0, 2, 3, 4, 6, 6], index=ser.index)
  345. tm.assert_series_equal(result, expected)
  346. @pytest.mark.parametrize(
  347. "func,closed,expected",
  348. [
  349. ("min", "right", [np.nan, 0, 0, 1, 2, 3, 4, 5, np.nan, np.nan]),
  350. ("min", "both", [np.nan, 0, 0, 0, 1, 2, 3, 4, 5, np.nan]),
  351. ("min", "neither", [np.nan, np.nan, 0, 1, 2, 3, 4, 5, np.nan, np.nan]),
  352. ("min", "left", [np.nan, np.nan, 0, 0, 1, 2, 3, 4, 5, np.nan]),
  353. ("max", "right", [np.nan, 1, 2, 3, 4, 5, 6, 6, np.nan, np.nan]),
  354. ("max", "both", [np.nan, 1, 2, 3, 4, 5, 6, 6, 6, np.nan]),
  355. ("max", "neither", [np.nan, np.nan, 1, 2, 3, 4, 5, 6, np.nan, np.nan]),
  356. ("max", "left", [np.nan, np.nan, 1, 2, 3, 4, 5, 6, 6, np.nan]),
  357. ],
  358. )
  359. def test_closed_min_max_minp(func, closed, expected):
  360. # see gh-21704
  361. ser = Series(data=np.arange(10), index=date_range("2000", periods=10))
  362. # Explicit cast to float to avoid implicit cast when setting nan
  363. ser = ser.astype("float")
  364. ser[ser.index[-3:]] = np.nan
  365. result = getattr(ser.rolling("3D", min_periods=2, closed=closed), func)()
  366. expected = Series(expected, index=ser.index)
  367. tm.assert_series_equal(result, expected)
  368. @pytest.mark.parametrize(
  369. "closed,expected",
  370. [
  371. ("right", [0, 0.5, 1, 2, 3, 4, 5, 6, 7, 8]),
  372. ("both", [0, 0.5, 1, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5]),
  373. ("neither", [np.nan, 0, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5]),
  374. ("left", [np.nan, 0, 0.5, 1, 2, 3, 4, 5, 6, 7]),
  375. ],
  376. )
  377. def test_closed_median_quantile(closed, expected):
  378. # GH 26005
  379. ser = Series(data=np.arange(10), index=date_range("2000", periods=10))
  380. roll = ser.rolling("3D", closed=closed)
  381. expected = Series(expected, index=ser.index)
  382. result = roll.median()
  383. tm.assert_series_equal(result, expected)
  384. result = roll.quantile(0.5)
  385. tm.assert_series_equal(result, expected)
  386. @pytest.mark.parametrize("roller", ["1s", 1])
  387. def tests_empty_df_rolling(roller):
  388. # GH 15819 Verifies that datetime and integer rolling windows can be
  389. # applied to empty DataFrames
  390. expected = DataFrame()
  391. result = DataFrame().rolling(roller).sum()
  392. tm.assert_frame_equal(result, expected)
  393. # Verifies that datetime and integer rolling windows can be applied to
  394. # empty DataFrames with datetime index
  395. expected = DataFrame(index=DatetimeIndex([]))
  396. result = DataFrame(index=DatetimeIndex([])).rolling(roller).sum()
  397. tm.assert_frame_equal(result, expected)
  398. def test_empty_window_median_quantile():
  399. # GH 26005
  400. expected = Series([np.nan, np.nan, np.nan])
  401. roll = Series(np.arange(3)).rolling(0)
  402. result = roll.median()
  403. tm.assert_series_equal(result, expected)
  404. result = roll.quantile(0.1)
  405. tm.assert_series_equal(result, expected)
  406. def test_missing_minp_zero():
  407. # https://github.com/pandas-dev/pandas/pull/18921
  408. # minp=0
  409. x = Series([np.nan])
  410. result = x.rolling(1, min_periods=0).sum()
  411. expected = Series([0.0])
  412. tm.assert_series_equal(result, expected)
  413. # minp=1
  414. result = x.rolling(1, min_periods=1).sum()
  415. expected = Series([np.nan])
  416. tm.assert_series_equal(result, expected)
  417. def test_missing_minp_zero_variable():
  418. # https://github.com/pandas-dev/pandas/pull/18921
  419. x = Series(
  420. [np.nan] * 4,
  421. index=DatetimeIndex(["2017-01-01", "2017-01-04", "2017-01-06", "2017-01-07"]),
  422. )
  423. result = x.rolling(Timedelta("2d"), min_periods=0).sum()
  424. expected = Series(0.0, index=x.index)
  425. tm.assert_series_equal(result, expected)
  426. def test_multi_index_names():
  427. # GH 16789, 16825
  428. cols = MultiIndex.from_product([["A", "B"], ["C", "D", "E"]], names=["1", "2"])
  429. df = DataFrame(np.ones((10, 6)), columns=cols)
  430. result = df.rolling(3).cov()
  431. tm.assert_index_equal(result.columns, df.columns)
  432. assert result.index.names == [None, "1", "2"]
  433. def test_rolling_axis_sum(axis_frame):
  434. # see gh-23372.
  435. df = DataFrame(np.ones((10, 20)))
  436. axis = df._get_axis_number(axis_frame)
  437. if axis == 0:
  438. expected = DataFrame({i: [np.nan] * 2 + [3.0] * 8 for i in range(20)})
  439. else:
  440. # axis == 1
  441. expected = DataFrame([[np.nan] * 2 + [3.0] * 18] * 10)
  442. result = df.rolling(3, axis=axis_frame).sum()
  443. tm.assert_frame_equal(result, expected)
  444. def test_rolling_axis_count(axis_frame):
  445. # see gh-26055
  446. df = DataFrame({"x": range(3), "y": range(3)})
  447. axis = df._get_axis_number(axis_frame)
  448. if axis in [0, "index"]:
  449. expected = DataFrame({"x": [1.0, 2.0, 2.0], "y": [1.0, 2.0, 2.0]})
  450. else:
  451. expected = DataFrame({"x": [1.0, 1.0, 1.0], "y": [2.0, 2.0, 2.0]})
  452. result = df.rolling(2, axis=axis_frame, min_periods=0).count()
  453. tm.assert_frame_equal(result, expected)
  454. def test_readonly_array():
  455. # GH-27766
  456. arr = np.array([1, 3, np.nan, 3, 5])
  457. arr.setflags(write=False)
  458. result = Series(arr).rolling(2).mean()
  459. expected = Series([np.nan, 2, np.nan, np.nan, 4])
  460. tm.assert_series_equal(result, expected)
  461. def test_rolling_datetime(axis_frame, tz_naive_fixture):
  462. # GH-28192
  463. tz = tz_naive_fixture
  464. df = DataFrame(
  465. {i: [1] * 2 for i in date_range("2019-8-01", "2019-08-03", freq="D", tz=tz)}
  466. )
  467. if axis_frame in [0, "index"]:
  468. result = df.T.rolling("2D", axis=axis_frame).sum().T
  469. else:
  470. result = df.rolling("2D", axis=axis_frame).sum()
  471. expected = DataFrame(
  472. {
  473. **{
  474. i: [1.0] * 2
  475. for i in date_range("2019-8-01", periods=1, freq="D", tz=tz)
  476. },
  477. **{
  478. i: [2.0] * 2
  479. for i in date_range("2019-8-02", "2019-8-03", freq="D", tz=tz)
  480. },
  481. }
  482. )
  483. tm.assert_frame_equal(result, expected)
  484. @pytest.mark.parametrize(
  485. "center, expected_data",
  486. [
  487. (
  488. True,
  489. (
  490. [88.0] * 7
  491. + [97.0] * 9
  492. + [98.0]
  493. + [99.0] * 21
  494. + [95.0] * 16
  495. + [93.0] * 5
  496. + [89.0] * 5
  497. + [96.0] * 21
  498. + [94.0] * 14
  499. + [90.0] * 13
  500. + [88.0] * 2
  501. + [90.0] * 9
  502. + [96.0] * 21
  503. + [95.0] * 6
  504. + [91.0]
  505. + [87.0] * 6
  506. + [92.0] * 21
  507. + [83.0] * 2
  508. + [86.0] * 10
  509. + [87.0] * 5
  510. + [98.0] * 21
  511. + [97.0] * 14
  512. + [93.0] * 7
  513. + [87.0] * 4
  514. + [86.0] * 4
  515. + [95.0] * 21
  516. + [85.0] * 14
  517. + [83.0] * 2
  518. + [76.0] * 5
  519. + [81.0] * 2
  520. + [98.0] * 21
  521. + [95.0] * 14
  522. + [91.0] * 7
  523. + [86.0]
  524. + [93.0] * 3
  525. + [95.0] * 29
  526. + [77.0] * 2
  527. ),
  528. ),
  529. (
  530. False,
  531. (
  532. [np.nan] * 2
  533. + [88.0] * 16
  534. + [97.0] * 9
  535. + [98.0]
  536. + [99.0] * 21
  537. + [95.0] * 16
  538. + [93.0] * 5
  539. + [89.0] * 5
  540. + [96.0] * 21
  541. + [94.0] * 14
  542. + [90.0] * 13
  543. + [88.0] * 2
  544. + [90.0] * 9
  545. + [96.0] * 21
  546. + [95.0] * 6
  547. + [91.0]
  548. + [87.0] * 6
  549. + [92.0] * 21
  550. + [83.0] * 2
  551. + [86.0] * 10
  552. + [87.0] * 5
  553. + [98.0] * 21
  554. + [97.0] * 14
  555. + [93.0] * 7
  556. + [87.0] * 4
  557. + [86.0] * 4
  558. + [95.0] * 21
  559. + [85.0] * 14
  560. + [83.0] * 2
  561. + [76.0] * 5
  562. + [81.0] * 2
  563. + [98.0] * 21
  564. + [95.0] * 14
  565. + [91.0] * 7
  566. + [86.0]
  567. + [93.0] * 3
  568. + [95.0] * 20
  569. ),
  570. ),
  571. ],
  572. )
  573. def test_rolling_window_as_string(center, expected_data):
  574. # see gh-22590
  575. date_today = datetime.now()
  576. days = date_range(date_today, date_today + timedelta(365), freq="D")
  577. npr = np.random.RandomState(seed=421)
  578. data = npr.randint(1, high=100, size=len(days))
  579. df = DataFrame({"DateCol": days, "metric": data})
  580. df.set_index("DateCol", inplace=True)
  581. result = df.rolling(window="21D", min_periods=2, closed="left", center=center)[
  582. "metric"
  583. ].agg("max")
  584. index = days.rename("DateCol")
  585. index = index._with_freq(None)
  586. expected = Series(expected_data, index=index, name="metric")
  587. tm.assert_series_equal(result, expected)
  588. def test_min_periods1():
  589. # GH#6795
  590. df = DataFrame([0, 1, 2, 1, 0], columns=["a"])
  591. result = df["a"].rolling(3, center=True, min_periods=1).max()
  592. expected = Series([1.0, 2.0, 2.0, 2.0, 1.0], name="a")
  593. tm.assert_series_equal(result, expected)
  594. def test_rolling_count_with_min_periods(frame_or_series):
  595. # GH 26996
  596. result = frame_or_series(range(5)).rolling(3, min_periods=3).count()
  597. expected = frame_or_series([np.nan, np.nan, 3.0, 3.0, 3.0])
  598. tm.assert_equal(result, expected)
  599. def test_rolling_count_default_min_periods_with_null_values(frame_or_series):
  600. # GH 26996
  601. values = [1, 2, 3, np.nan, 4, 5, 6]
  602. expected_counts = [1.0, 2.0, 3.0, 2.0, 2.0, 2.0, 3.0]
  603. # GH 31302
  604. result = frame_or_series(values).rolling(3, min_periods=0).count()
  605. expected = frame_or_series(expected_counts)
  606. tm.assert_equal(result, expected)
  607. @pytest.mark.parametrize(
  608. "df,expected,window,min_periods",
  609. [
  610. (
  611. DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}),
  612. [
  613. ({"A": [1], "B": [4]}, [0]),
  614. ({"A": [1, 2], "B": [4, 5]}, [0, 1]),
  615. ({"A": [1, 2, 3], "B": [4, 5, 6]}, [0, 1, 2]),
  616. ],
  617. 3,
  618. None,
  619. ),
  620. (
  621. DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}),
  622. [
  623. ({"A": [1], "B": [4]}, [0]),
  624. ({"A": [1, 2], "B": [4, 5]}, [0, 1]),
  625. ({"A": [2, 3], "B": [5, 6]}, [1, 2]),
  626. ],
  627. 2,
  628. 1,
  629. ),
  630. (
  631. DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}),
  632. [
  633. ({"A": [1], "B": [4]}, [0]),
  634. ({"A": [1, 2], "B": [4, 5]}, [0, 1]),
  635. ({"A": [2, 3], "B": [5, 6]}, [1, 2]),
  636. ],
  637. 2,
  638. 2,
  639. ),
  640. (
  641. DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}),
  642. [
  643. ({"A": [1], "B": [4]}, [0]),
  644. ({"A": [2], "B": [5]}, [1]),
  645. ({"A": [3], "B": [6]}, [2]),
  646. ],
  647. 1,
  648. 1,
  649. ),
  650. (
  651. DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}),
  652. [
  653. ({"A": [1], "B": [4]}, [0]),
  654. ({"A": [2], "B": [5]}, [1]),
  655. ({"A": [3], "B": [6]}, [2]),
  656. ],
  657. 1,
  658. 0,
  659. ),
  660. (DataFrame({"A": [1], "B": [4]}), [], 2, None),
  661. (DataFrame({"A": [1], "B": [4]}), [], 2, 1),
  662. (DataFrame(), [({}, [])], 2, None),
  663. (
  664. DataFrame({"A": [1, np.nan, 3], "B": [np.nan, 5, 6]}),
  665. [
  666. ({"A": [1.0], "B": [np.nan]}, [0]),
  667. ({"A": [1, np.nan], "B": [np.nan, 5]}, [0, 1]),
  668. ({"A": [1, np.nan, 3], "B": [np.nan, 5, 6]}, [0, 1, 2]),
  669. ],
  670. 3,
  671. 2,
  672. ),
  673. ],
  674. )
  675. def test_iter_rolling_dataframe(df, expected, window, min_periods):
  676. # GH 11704
  677. expected = [DataFrame(values, index=index) for (values, index) in expected]
  678. for expected, actual in zip(expected, df.rolling(window, min_periods=min_periods)):
  679. tm.assert_frame_equal(actual, expected)
  680. @pytest.mark.parametrize(
  681. "expected,window",
  682. [
  683. (
  684. [
  685. ({"A": [1], "B": [4]}, [0]),
  686. ({"A": [1, 2], "B": [4, 5]}, [0, 1]),
  687. ({"A": [2, 3], "B": [5, 6]}, [1, 2]),
  688. ],
  689. "2D",
  690. ),
  691. (
  692. [
  693. ({"A": [1], "B": [4]}, [0]),
  694. ({"A": [1, 2], "B": [4, 5]}, [0, 1]),
  695. ({"A": [1, 2, 3], "B": [4, 5, 6]}, [0, 1, 2]),
  696. ],
  697. "3D",
  698. ),
  699. (
  700. [
  701. ({"A": [1], "B": [4]}, [0]),
  702. ({"A": [2], "B": [5]}, [1]),
  703. ({"A": [3], "B": [6]}, [2]),
  704. ],
  705. "1D",
  706. ),
  707. ],
  708. )
  709. def test_iter_rolling_on_dataframe(expected, window):
  710. # GH 11704, 40373
  711. df = DataFrame(
  712. {
  713. "A": [1, 2, 3, 4, 5],
  714. "B": [4, 5, 6, 7, 8],
  715. "C": date_range(start="2016-01-01", periods=5, freq="D"),
  716. }
  717. )
  718. expected = [
  719. DataFrame(values, index=df.loc[index, "C"]) for (values, index) in expected
  720. ]
  721. for expected, actual in zip(expected, df.rolling(window, on="C")):
  722. tm.assert_frame_equal(actual, expected)
  723. def test_iter_rolling_on_dataframe_unordered():
  724. # GH 43386
  725. df = DataFrame({"a": ["x", "y", "x"], "b": [0, 1, 2]})
  726. results = list(df.groupby("a").rolling(2))
  727. expecteds = [df.iloc[idx, [1]] for idx in [[0], [0, 2], [1]]]
  728. for result, expected in zip(results, expecteds):
  729. tm.assert_frame_equal(result, expected)
  730. @pytest.mark.parametrize(
  731. "ser,expected,window, min_periods",
  732. [
  733. (
  734. Series([1, 2, 3]),
  735. [([1], [0]), ([1, 2], [0, 1]), ([1, 2, 3], [0, 1, 2])],
  736. 3,
  737. None,
  738. ),
  739. (
  740. Series([1, 2, 3]),
  741. [([1], [0]), ([1, 2], [0, 1]), ([1, 2, 3], [0, 1, 2])],
  742. 3,
  743. 1,
  744. ),
  745. (
  746. Series([1, 2, 3]),
  747. [([1], [0]), ([1, 2], [0, 1]), ([2, 3], [1, 2])],
  748. 2,
  749. 1,
  750. ),
  751. (
  752. Series([1, 2, 3]),
  753. [([1], [0]), ([1, 2], [0, 1]), ([2, 3], [1, 2])],
  754. 2,
  755. 2,
  756. ),
  757. (Series([1, 2, 3]), [([1], [0]), ([2], [1]), ([3], [2])], 1, 0),
  758. (Series([1, 2, 3]), [([1], [0]), ([2], [1]), ([3], [2])], 1, 1),
  759. (Series([1, 2]), [([1], [0]), ([1, 2], [0, 1])], 2, 0),
  760. (Series([], dtype="int64"), [], 2, 1),
  761. ],
  762. )
  763. def test_iter_rolling_series(ser, expected, window, min_periods):
  764. # GH 11704
  765. expected = [Series(values, index=index) for (values, index) in expected]
  766. for expected, actual in zip(expected, ser.rolling(window, min_periods=min_periods)):
  767. tm.assert_series_equal(actual, expected)
  768. @pytest.mark.parametrize(
  769. "expected,expected_index,window",
  770. [
  771. (
  772. [[0], [1], [2], [3], [4]],
  773. [
  774. date_range("2020-01-01", periods=1, freq="D"),
  775. date_range("2020-01-02", periods=1, freq="D"),
  776. date_range("2020-01-03", periods=1, freq="D"),
  777. date_range("2020-01-04", periods=1, freq="D"),
  778. date_range("2020-01-05", periods=1, freq="D"),
  779. ],
  780. "1D",
  781. ),
  782. (
  783. [[0], [0, 1], [1, 2], [2, 3], [3, 4]],
  784. [
  785. date_range("2020-01-01", periods=1, freq="D"),
  786. date_range("2020-01-01", periods=2, freq="D"),
  787. date_range("2020-01-02", periods=2, freq="D"),
  788. date_range("2020-01-03", periods=2, freq="D"),
  789. date_range("2020-01-04", periods=2, freq="D"),
  790. ],
  791. "2D",
  792. ),
  793. (
  794. [[0], [0, 1], [0, 1, 2], [1, 2, 3], [2, 3, 4]],
  795. [
  796. date_range("2020-01-01", periods=1, freq="D"),
  797. date_range("2020-01-01", periods=2, freq="D"),
  798. date_range("2020-01-01", periods=3, freq="D"),
  799. date_range("2020-01-02", periods=3, freq="D"),
  800. date_range("2020-01-03", periods=3, freq="D"),
  801. ],
  802. "3D",
  803. ),
  804. ],
  805. )
  806. def test_iter_rolling_datetime(expected, expected_index, window):
  807. # GH 11704
  808. ser = Series(range(5), index=date_range(start="2020-01-01", periods=5, freq="D"))
  809. expected = [
  810. Series(values, index=idx) for (values, idx) in zip(expected, expected_index)
  811. ]
  812. for expected, actual in zip(expected, ser.rolling(window)):
  813. tm.assert_series_equal(actual, expected)
  814. @pytest.mark.parametrize(
  815. "grouping,_index",
  816. [
  817. (
  818. {"level": 0},
  819. MultiIndex.from_tuples(
  820. [(0, 0), (0, 0), (1, 1), (1, 1), (1, 1)], names=[None, None]
  821. ),
  822. ),
  823. (
  824. {"by": "X"},
  825. MultiIndex.from_tuples(
  826. [(0, 0), (1, 0), (2, 1), (3, 1), (4, 1)], names=["X", None]
  827. ),
  828. ),
  829. ],
  830. )
  831. def test_rolling_positional_argument(grouping, _index, raw):
  832. # GH 34605
  833. def scaled_sum(*args):
  834. if len(args) < 2:
  835. raise ValueError("The function needs two arguments")
  836. array, scale = args
  837. return array.sum() / scale
  838. df = DataFrame(data={"X": range(5)}, index=[0, 0, 1, 1, 1])
  839. expected = DataFrame(data={"X": [0.0, 0.5, 1.0, 1.5, 2.0]}, index=_index)
  840. # GH 40341
  841. if "by" in grouping:
  842. expected = expected.drop(columns="X", errors="ignore")
  843. result = df.groupby(**grouping).rolling(1).apply(scaled_sum, raw=raw, args=(2,))
  844. tm.assert_frame_equal(result, expected)
  845. @pytest.mark.parametrize("add", [0.0, 2.0])
  846. def test_rolling_numerical_accuracy_kahan_mean(add):
  847. # GH: 36031 implementing kahan summation
  848. df = DataFrame(
  849. {"A": [3002399751580331.0 + add, -0.0, -0.0]},
  850. index=[
  851. Timestamp("19700101 09:00:00"),
  852. Timestamp("19700101 09:00:03"),
  853. Timestamp("19700101 09:00:06"),
  854. ],
  855. )
  856. result = (
  857. df.resample("1s").ffill().rolling("3s", closed="left", min_periods=3).mean()
  858. )
  859. dates = date_range("19700101 09:00:00", periods=7, freq="S")
  860. expected = DataFrame(
  861. {
  862. "A": [
  863. np.nan,
  864. np.nan,
  865. np.nan,
  866. 3002399751580330.5,
  867. 2001599834386887.25,
  868. 1000799917193443.625,
  869. 0.0,
  870. ]
  871. },
  872. index=dates,
  873. )
  874. tm.assert_frame_equal(result, expected)
  875. def test_rolling_numerical_accuracy_kahan_sum():
  876. # GH: 13254
  877. df = DataFrame([2.186, -1.647, 0.0, 0.0, 0.0, 0.0], columns=["x"])
  878. result = df["x"].rolling(3).sum()
  879. expected = Series([np.nan, np.nan, 0.539, -1.647, 0.0, 0.0], name="x")
  880. tm.assert_series_equal(result, expected)
  881. def test_rolling_numerical_accuracy_jump():
  882. # GH: 32761
  883. index = date_range(start="2020-01-01", end="2020-01-02", freq="60s").append(
  884. DatetimeIndex(["2020-01-03"])
  885. )
  886. data = np.random.rand(len(index))
  887. df = DataFrame({"data": data}, index=index)
  888. result = df.rolling("60s").mean()
  889. tm.assert_frame_equal(result, df[["data"]])
  890. def test_rolling_numerical_accuracy_small_values():
  891. # GH: 10319
  892. s = Series(
  893. data=[0.00012456, 0.0003, -0.0, -0.0],
  894. index=date_range("1999-02-03", "1999-02-06"),
  895. )
  896. result = s.rolling(1).mean()
  897. tm.assert_series_equal(result, s)
  898. def test_rolling_numerical_too_large_numbers():
  899. # GH: 11645
  900. dates = date_range("2015-01-01", periods=10, freq="D")
  901. ds = Series(data=range(10), index=dates, dtype=np.float64)
  902. ds[2] = -9e33
  903. result = ds.rolling(5).mean()
  904. expected = Series(
  905. [
  906. np.nan,
  907. np.nan,
  908. np.nan,
  909. np.nan,
  910. -1.8e33,
  911. -1.8e33,
  912. -1.8e33,
  913. 5.0,
  914. 6.0,
  915. 7.0,
  916. ],
  917. index=dates,
  918. )
  919. tm.assert_series_equal(result, expected)
  920. @pytest.mark.parametrize(
  921. ("func", "value"),
  922. [("sum", 2.0), ("max", 1.0), ("min", 1.0), ("mean", 1.0), ("median", 1.0)],
  923. )
  924. def test_rolling_mixed_dtypes_axis_1(func, value):
  925. # GH: 20649
  926. df = DataFrame(1, index=[1, 2], columns=["a", "b", "c"])
  927. df["c"] = 1.0
  928. result = getattr(df.rolling(window=2, min_periods=1, axis=1), func)()
  929. expected = DataFrame(
  930. {"a": [1.0, 1.0], "b": [value, value], "c": [value, value]},
  931. index=[1, 2],
  932. )
  933. tm.assert_frame_equal(result, expected)
  934. def test_rolling_axis_one_with_nan():
  935. # GH: 35596
  936. df = DataFrame(
  937. [
  938. [0, 1, 2, 4, np.nan, np.nan, np.nan],
  939. [0, 1, 2, np.nan, np.nan, np.nan, np.nan],
  940. [0, 2, 2, np.nan, 2, np.nan, 1],
  941. ]
  942. )
  943. result = df.rolling(window=7, min_periods=1, axis="columns").sum()
  944. expected = DataFrame(
  945. [
  946. [0.0, 1.0, 3.0, 7.0, 7.0, 7.0, 7.0],
  947. [0.0, 1.0, 3.0, 3.0, 3.0, 3.0, 3.0],
  948. [0.0, 2.0, 4.0, 4.0, 6.0, 6.0, 7.0],
  949. ]
  950. )
  951. tm.assert_frame_equal(result, expected)
  952. @pytest.mark.parametrize(
  953. "value",
  954. ["test", to_datetime("2019-12-31"), to_timedelta("1 days 06:05:01.00003")],
  955. )
  956. def test_rolling_axis_1_non_numeric_dtypes(value):
  957. # GH: 20649
  958. df = DataFrame({"a": [1, 2]})
  959. df["b"] = value
  960. result = df.rolling(window=2, min_periods=1, axis=1).sum()
  961. expected = DataFrame({"a": [1.0, 2.0]})
  962. tm.assert_frame_equal(result, expected)
  963. def test_rolling_on_df_transposed():
  964. # GH: 32724
  965. df = DataFrame({"A": [1, None], "B": [4, 5], "C": [7, 8]})
  966. expected = DataFrame({"A": [1.0, np.nan], "B": [5.0, 5.0], "C": [11.0, 13.0]})
  967. result = df.rolling(min_periods=1, window=2, axis=1).sum()
  968. tm.assert_frame_equal(result, expected)
  969. result = df.T.rolling(min_periods=1, window=2).sum().T
  970. tm.assert_frame_equal(result, expected)
  971. @pytest.mark.parametrize(
  972. ("index", "window"),
  973. [
  974. (
  975. period_range(start="2020-01-01 08:00", end="2020-01-01 08:08", freq="T"),
  976. "2T",
  977. ),
  978. (
  979. period_range(start="2020-01-01 08:00", end="2020-01-01 12:00", freq="30T"),
  980. "1h",
  981. ),
  982. ],
  983. )
  984. @pytest.mark.parametrize(
  985. ("func", "values"),
  986. [
  987. ("min", [np.nan, 0, 0, 1, 2, 3, 4, 5, 6]),
  988. ("max", [np.nan, 0, 1, 2, 3, 4, 5, 6, 7]),
  989. ("sum", [np.nan, 0, 1, 3, 5, 7, 9, 11, 13]),
  990. ],
  991. )
  992. def test_rolling_period_index(index, window, func, values):
  993. # GH: 34225
  994. ds = Series([0, 1, 2, 3, 4, 5, 6, 7, 8], index=index)
  995. result = getattr(ds.rolling(window, closed="left"), func)()
  996. expected = Series(values, index=index)
  997. tm.assert_series_equal(result, expected)
  998. def test_rolling_sem(frame_or_series):
  999. # GH: 26476
  1000. obj = frame_or_series([0, 1, 2])
  1001. result = obj.rolling(2, min_periods=1).sem()
  1002. if isinstance(result, DataFrame):
  1003. result = Series(result[0].values)
  1004. expected = Series([np.nan] + [0.7071067811865476] * 2)
  1005. tm.assert_series_equal(result, expected)
  1006. @pytest.mark.xfail(
  1007. (is_platform_arm() and not is_platform_mac()) or is_platform_power(),
  1008. reason="GH 38921",
  1009. )
  1010. @pytest.mark.parametrize(
  1011. ("func", "third_value", "values"),
  1012. [
  1013. ("var", 1, [5e33, 0, 0.5, 0.5, 2, 0]),
  1014. ("std", 1, [7.071068e16, 0, 0.7071068, 0.7071068, 1.414214, 0]),
  1015. ("var", 2, [5e33, 0.5, 0, 0.5, 2, 0]),
  1016. ("std", 2, [7.071068e16, 0.7071068, 0, 0.7071068, 1.414214, 0]),
  1017. ],
  1018. )
  1019. def test_rolling_var_numerical_issues(func, third_value, values):
  1020. # GH: 37051
  1021. ds = Series([99999999999999999, 1, third_value, 2, 3, 1, 1])
  1022. result = getattr(ds.rolling(2), func)()
  1023. expected = Series([np.nan] + values)
  1024. tm.assert_series_equal(result, expected)
  1025. # GH 42064
  1026. # new `roll_var` will output 0.0 correctly
  1027. tm.assert_series_equal(result == 0, expected == 0)
  1028. def test_timeoffset_as_window_parameter_for_corr():
  1029. # GH: 28266
  1030. exp = DataFrame(
  1031. {
  1032. "B": [
  1033. np.nan,
  1034. np.nan,
  1035. 0.9999999999999998,
  1036. -1.0,
  1037. 1.0,
  1038. -0.3273268353539892,
  1039. 0.9999999999999998,
  1040. 1.0,
  1041. 0.9999999999999998,
  1042. 1.0,
  1043. ],
  1044. "A": [
  1045. np.nan,
  1046. np.nan,
  1047. -1.0,
  1048. 1.0000000000000002,
  1049. -0.3273268353539892,
  1050. 0.9999999999999966,
  1051. 1.0,
  1052. 1.0000000000000002,
  1053. 1.0,
  1054. 1.0000000000000002,
  1055. ],
  1056. },
  1057. index=MultiIndex.from_tuples(
  1058. [
  1059. (Timestamp("20130101 09:00:00"), "B"),
  1060. (Timestamp("20130101 09:00:00"), "A"),
  1061. (Timestamp("20130102 09:00:02"), "B"),
  1062. (Timestamp("20130102 09:00:02"), "A"),
  1063. (Timestamp("20130103 09:00:03"), "B"),
  1064. (Timestamp("20130103 09:00:03"), "A"),
  1065. (Timestamp("20130105 09:00:05"), "B"),
  1066. (Timestamp("20130105 09:00:05"), "A"),
  1067. (Timestamp("20130106 09:00:06"), "B"),
  1068. (Timestamp("20130106 09:00:06"), "A"),
  1069. ]
  1070. ),
  1071. )
  1072. df = DataFrame(
  1073. {"B": [0, 1, 2, 4, 3], "A": [7, 4, 6, 9, 3]},
  1074. index=[
  1075. Timestamp("20130101 09:00:00"),
  1076. Timestamp("20130102 09:00:02"),
  1077. Timestamp("20130103 09:00:03"),
  1078. Timestamp("20130105 09:00:05"),
  1079. Timestamp("20130106 09:00:06"),
  1080. ],
  1081. )
  1082. res = df.rolling(window="3d").corr()
  1083. tm.assert_frame_equal(exp, res)
  1084. @pytest.mark.parametrize("method", ["var", "sum", "mean", "skew", "kurt", "min", "max"])
  1085. def test_rolling_decreasing_indices(method):
  1086. """
  1087. Make sure that decreasing indices give the same results as increasing indices.
  1088. GH 36933
  1089. """
  1090. df = DataFrame({"values": np.arange(-15, 10) ** 2})
  1091. df_reverse = DataFrame({"values": df["values"][::-1]}, index=df.index[::-1])
  1092. increasing = getattr(df.rolling(window=5), method)()
  1093. decreasing = getattr(df_reverse.rolling(window=5), method)()
  1094. assert np.abs(decreasing.values[::-1][:-4] - increasing.values[4:]).max() < 1e-12
  1095. @pytest.mark.parametrize(
  1096. "window,closed,expected",
  1097. [
  1098. ("2s", "right", [1.0, 3.0, 5.0, 3.0]),
  1099. ("2s", "left", [0.0, 1.0, 3.0, 5.0]),
  1100. ("2s", "both", [1.0, 3.0, 6.0, 5.0]),
  1101. ("2s", "neither", [0.0, 1.0, 2.0, 3.0]),
  1102. ("3s", "right", [1.0, 3.0, 6.0, 5.0]),
  1103. ("3s", "left", [1.0, 3.0, 6.0, 5.0]),
  1104. ("3s", "both", [1.0, 3.0, 6.0, 5.0]),
  1105. ("3s", "neither", [1.0, 3.0, 6.0, 5.0]),
  1106. ],
  1107. )
  1108. def test_rolling_decreasing_indices_centered(window, closed, expected, frame_or_series):
  1109. """
  1110. Ensure that a symmetrical inverted index return same result as non-inverted.
  1111. """
  1112. # GH 43927
  1113. index = date_range("2020", periods=4, freq="1s")
  1114. df_inc = frame_or_series(range(4), index=index)
  1115. df_dec = frame_or_series(range(4), index=index[::-1])
  1116. expected_inc = frame_or_series(expected, index=index)
  1117. expected_dec = frame_or_series(expected, index=index[::-1])
  1118. result_inc = df_inc.rolling(window, closed=closed, center=True).sum()
  1119. result_dec = df_dec.rolling(window, closed=closed, center=True).sum()
  1120. tm.assert_equal(result_inc, expected_inc)
  1121. tm.assert_equal(result_dec, expected_dec)
  1122. @pytest.mark.parametrize(
  1123. "window,expected",
  1124. [
  1125. ("1ns", [1.0, 1.0, 1.0, 1.0]),
  1126. ("3ns", [2.0, 3.0, 3.0, 2.0]),
  1127. ],
  1128. )
  1129. def test_rolling_center_nanosecond_resolution(
  1130. window, closed, expected, frame_or_series
  1131. ):
  1132. index = date_range("2020", periods=4, freq="1ns")
  1133. df = frame_or_series([1, 1, 1, 1], index=index, dtype=float)
  1134. expected = frame_or_series(expected, index=index, dtype=float)
  1135. result = df.rolling(window, closed=closed, center=True).sum()
  1136. tm.assert_equal(result, expected)
  1137. @pytest.mark.parametrize(
  1138. "method,expected",
  1139. [
  1140. (
  1141. "var",
  1142. [
  1143. float("nan"),
  1144. 43.0,
  1145. float("nan"),
  1146. 136.333333,
  1147. 43.5,
  1148. 94.966667,
  1149. 182.0,
  1150. 318.0,
  1151. ],
  1152. ),
  1153. (
  1154. "mean",
  1155. [float("nan"), 7.5, float("nan"), 21.5, 6.0, 9.166667, 13.0, 17.5],
  1156. ),
  1157. (
  1158. "sum",
  1159. [float("nan"), 30.0, float("nan"), 86.0, 30.0, 55.0, 91.0, 140.0],
  1160. ),
  1161. (
  1162. "skew",
  1163. [
  1164. float("nan"),
  1165. 0.709296,
  1166. float("nan"),
  1167. 0.407073,
  1168. 0.984656,
  1169. 0.919184,
  1170. 0.874674,
  1171. 0.842418,
  1172. ],
  1173. ),
  1174. (
  1175. "kurt",
  1176. [
  1177. float("nan"),
  1178. -0.5916711736073559,
  1179. float("nan"),
  1180. -1.0028993131317954,
  1181. -0.06103844629409494,
  1182. -0.254143227116194,
  1183. -0.37362637362637585,
  1184. -0.45439658241367054,
  1185. ],
  1186. ),
  1187. ],
  1188. )
  1189. def test_rolling_non_monotonic(method, expected):
  1190. """
  1191. Make sure the (rare) branch of non-monotonic indices is covered by a test.
  1192. output from 1.1.3 is assumed to be the expected output. Output of sum/mean has
  1193. manually been verified.
  1194. GH 36933.
  1195. """
  1196. # Based on an example found in computation.rst
  1197. use_expanding = [True, False, True, False, True, True, True, True]
  1198. df = DataFrame({"values": np.arange(len(use_expanding)) ** 2})
  1199. class CustomIndexer(BaseIndexer):
  1200. def get_window_bounds(self, num_values, min_periods, center, closed, step):
  1201. start = np.empty(num_values, dtype=np.int64)
  1202. end = np.empty(num_values, dtype=np.int64)
  1203. for i in range(num_values):
  1204. if self.use_expanding[i]:
  1205. start[i] = 0
  1206. end[i] = i + 1
  1207. else:
  1208. start[i] = i
  1209. end[i] = i + self.window_size
  1210. return start, end
  1211. indexer = CustomIndexer(window_size=4, use_expanding=use_expanding)
  1212. result = getattr(df.rolling(indexer), method)()
  1213. expected = DataFrame({"values": expected})
  1214. tm.assert_frame_equal(result, expected)
  1215. @pytest.mark.parametrize(
  1216. ("index", "window"),
  1217. [
  1218. ([0, 1, 2, 3, 4], 2),
  1219. (date_range("2001-01-01", freq="D", periods=5), "2D"),
  1220. ],
  1221. )
  1222. def test_rolling_corr_timedelta_index(index, window):
  1223. # GH: 31286
  1224. x = Series([1, 2, 3, 4, 5], index=index)
  1225. y = x.copy()
  1226. x.iloc[0:2] = 0.0
  1227. result = x.rolling(window).corr(y)
  1228. expected = Series([np.nan, np.nan, 1, 1, 1], index=index)
  1229. tm.assert_almost_equal(result, expected)
  1230. def test_groupby_rolling_nan_included():
  1231. # GH 35542
  1232. data = {"group": ["g1", np.nan, "g1", "g2", np.nan], "B": [0, 1, 2, 3, 4]}
  1233. df = DataFrame(data)
  1234. result = df.groupby("group", dropna=False).rolling(1, min_periods=1).mean()
  1235. expected = DataFrame(
  1236. {"B": [0.0, 2.0, 3.0, 1.0, 4.0]},
  1237. # GH-38057 from_tuples puts the NaNs in the codes, result expects them
  1238. # to be in the levels, at the moment
  1239. # index=MultiIndex.from_tuples(
  1240. # [("g1", 0), ("g1", 2), ("g2", 3), (np.nan, 1), (np.nan, 4)],
  1241. # names=["group", None],
  1242. # ),
  1243. index=MultiIndex(
  1244. [["g1", "g2", np.nan], [0, 1, 2, 3, 4]],
  1245. [[0, 0, 1, 2, 2], [0, 2, 3, 1, 4]],
  1246. names=["group", None],
  1247. ),
  1248. )
  1249. tm.assert_frame_equal(result, expected)
  1250. @pytest.mark.parametrize("method", ["skew", "kurt"])
  1251. def test_rolling_skew_kurt_numerical_stability(method):
  1252. # GH#6929
  1253. ser = Series(np.random.rand(10))
  1254. ser_copy = ser.copy()
  1255. expected = getattr(ser.rolling(3), method)()
  1256. tm.assert_series_equal(ser, ser_copy)
  1257. ser = ser + 50000
  1258. result = getattr(ser.rolling(3), method)()
  1259. tm.assert_series_equal(result, expected)
  1260. @pytest.mark.parametrize(
  1261. ("method", "values"),
  1262. [
  1263. ("skew", [2.0, 0.854563, 0.0, 1.999984]),
  1264. ("kurt", [4.0, -1.289256, -1.2, 3.999946]),
  1265. ],
  1266. )
  1267. def test_rolling_skew_kurt_large_value_range(method, values):
  1268. # GH: 37557
  1269. s = Series([3000000, 1, 1, 2, 3, 4, 999])
  1270. result = getattr(s.rolling(4), method)()
  1271. expected = Series([np.nan] * 3 + values)
  1272. tm.assert_series_equal(result, expected)
  1273. def test_invalid_method():
  1274. with pytest.raises(ValueError, match="method must be 'table' or 'single"):
  1275. Series(range(1)).rolling(1, method="foo")
  1276. @pytest.mark.parametrize("window", [1, "1d"])
  1277. def test_rolling_descending_date_order_with_offset(window, frame_or_series):
  1278. # GH#40002
  1279. idx = date_range(start="2020-01-01", end="2020-01-03", freq="1d")
  1280. obj = frame_or_series(range(1, 4), index=idx)
  1281. result = obj.rolling("1d", closed="left").sum()
  1282. expected = frame_or_series([np.nan, 1, 2], index=idx)
  1283. tm.assert_equal(result, expected)
  1284. result = obj.iloc[::-1].rolling("1d", closed="left").sum()
  1285. idx = date_range(start="2020-01-03", end="2020-01-01", freq="-1d")
  1286. expected = frame_or_series([np.nan, 3, 2], index=idx)
  1287. tm.assert_equal(result, expected)
  1288. def test_rolling_var_floating_artifact_precision():
  1289. # GH 37051
  1290. s = Series([7, 5, 5, 5])
  1291. result = s.rolling(3).var()
  1292. expected = Series([np.nan, np.nan, 4 / 3, 0])
  1293. tm.assert_series_equal(result, expected, atol=1.0e-15, rtol=1.0e-15)
  1294. # GH 42064
  1295. # new `roll_var` will output 0.0 correctly
  1296. tm.assert_series_equal(result == 0, expected == 0)
  1297. def test_rolling_std_small_values():
  1298. # GH 37051
  1299. s = Series(
  1300. [
  1301. 0.00000054,
  1302. 0.00000053,
  1303. 0.00000054,
  1304. ]
  1305. )
  1306. result = s.rolling(2).std()
  1307. expected = Series([np.nan, 7.071068e-9, 7.071068e-9])
  1308. tm.assert_series_equal(result, expected, atol=1.0e-15, rtol=1.0e-15)
  1309. @pytest.mark.parametrize(
  1310. "start, exp_values",
  1311. [
  1312. (1, [0.03, 0.0155, 0.0155, 0.011, 0.01025]),
  1313. (2, [0.001, 0.001, 0.0015, 0.00366666]),
  1314. ],
  1315. )
  1316. def test_rolling_mean_all_nan_window_floating_artifacts(start, exp_values):
  1317. # GH#41053
  1318. df = DataFrame(
  1319. [
  1320. 0.03,
  1321. 0.03,
  1322. 0.001,
  1323. np.NaN,
  1324. 0.002,
  1325. 0.008,
  1326. np.NaN,
  1327. np.NaN,
  1328. np.NaN,
  1329. np.NaN,
  1330. np.NaN,
  1331. np.NaN,
  1332. 0.005,
  1333. 0.2,
  1334. ]
  1335. )
  1336. values = exp_values + [
  1337. 0.00366666,
  1338. 0.005,
  1339. 0.005,
  1340. 0.008,
  1341. np.NaN,
  1342. np.NaN,
  1343. 0.005,
  1344. 0.102500,
  1345. ]
  1346. expected = DataFrame(
  1347. values,
  1348. index=list(range(start, len(values) + start)),
  1349. )
  1350. result = df.iloc[start:].rolling(5, min_periods=0).mean()
  1351. tm.assert_frame_equal(result, expected)
  1352. def test_rolling_sum_all_nan_window_floating_artifacts():
  1353. # GH#41053
  1354. df = DataFrame([0.002, 0.008, 0.005, np.NaN, np.NaN, np.NaN])
  1355. result = df.rolling(3, min_periods=0).sum()
  1356. expected = DataFrame([0.002, 0.010, 0.015, 0.013, 0.005, 0.0])
  1357. tm.assert_frame_equal(result, expected)
  1358. def test_rolling_zero_window():
  1359. # GH 22719
  1360. s = Series(range(1))
  1361. result = s.rolling(0).min()
  1362. expected = Series([np.nan])
  1363. tm.assert_series_equal(result, expected)
  1364. def test_rolling_float_dtype(float_numpy_dtype):
  1365. # GH#42452
  1366. df = DataFrame({"A": range(5), "B": range(10, 15)}, dtype=float_numpy_dtype)
  1367. expected = DataFrame(
  1368. {"A": [np.nan] * 5, "B": range(10, 20, 2)},
  1369. dtype=float_numpy_dtype,
  1370. )
  1371. result = df.rolling(2, axis=1).sum()
  1372. tm.assert_frame_equal(result, expected, check_dtype=False)
  1373. def test_rolling_numeric_dtypes():
  1374. # GH#41779
  1375. df = DataFrame(np.arange(40).reshape(4, 10), columns=list("abcdefghij")).astype(
  1376. {
  1377. "a": "float16",
  1378. "b": "float32",
  1379. "c": "float64",
  1380. "d": "int8",
  1381. "e": "int16",
  1382. "f": "int32",
  1383. "g": "uint8",
  1384. "h": "uint16",
  1385. "i": "uint32",
  1386. "j": "uint64",
  1387. }
  1388. )
  1389. result = df.rolling(window=2, min_periods=1, axis=1).min()
  1390. expected = DataFrame(
  1391. {
  1392. "a": range(0, 40, 10),
  1393. "b": range(0, 40, 10),
  1394. "c": range(1, 40, 10),
  1395. "d": range(2, 40, 10),
  1396. "e": range(3, 40, 10),
  1397. "f": range(4, 40, 10),
  1398. "g": range(5, 40, 10),
  1399. "h": range(6, 40, 10),
  1400. "i": range(7, 40, 10),
  1401. "j": range(8, 40, 10),
  1402. },
  1403. dtype="float64",
  1404. )
  1405. tm.assert_frame_equal(result, expected)
  1406. @pytest.mark.parametrize("window", [1, 3, 10, 20])
  1407. @pytest.mark.parametrize("method", ["min", "max", "average"])
  1408. @pytest.mark.parametrize("pct", [True, False])
  1409. @pytest.mark.parametrize("ascending", [True, False])
  1410. @pytest.mark.parametrize("test_data", ["default", "duplicates", "nans"])
  1411. def test_rank(window, method, pct, ascending, test_data):
  1412. length = 20
  1413. if test_data == "default":
  1414. ser = Series(data=np.random.rand(length))
  1415. elif test_data == "duplicates":
  1416. ser = Series(data=np.random.choice(3, length))
  1417. elif test_data == "nans":
  1418. ser = Series(
  1419. data=np.random.choice([1.0, 0.25, 0.75, np.nan, np.inf, -np.inf], length)
  1420. )
  1421. expected = ser.rolling(window).apply(
  1422. lambda x: x.rank(method=method, pct=pct, ascending=ascending).iloc[-1]
  1423. )
  1424. result = ser.rolling(window).rank(method=method, pct=pct, ascending=ascending)
  1425. tm.assert_series_equal(result, expected)
  1426. def test_rolling_quantile_np_percentile():
  1427. # #9413: Tests that rolling window's quantile default behavior
  1428. # is analogous to Numpy's percentile
  1429. row = 10
  1430. col = 5
  1431. idx = date_range("20100101", periods=row, freq="B")
  1432. df = DataFrame(np.random.rand(row * col).reshape((row, -1)), index=idx)
  1433. df_quantile = df.quantile([0.25, 0.5, 0.75], axis=0)
  1434. np_percentile = np.percentile(df, [25, 50, 75], axis=0)
  1435. tm.assert_almost_equal(df_quantile.values, np.array(np_percentile))
  1436. @pytest.mark.parametrize("quantile", [0.0, 0.1, 0.45, 0.5, 1])
  1437. @pytest.mark.parametrize(
  1438. "interpolation", ["linear", "lower", "higher", "nearest", "midpoint"]
  1439. )
  1440. @pytest.mark.parametrize(
  1441. "data",
  1442. [
  1443. [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0],
  1444. [8.0, 1.0, 3.0, 4.0, 5.0, 2.0, 6.0, 7.0],
  1445. [0.0, np.nan, 0.2, np.nan, 0.4],
  1446. [np.nan, np.nan, np.nan, np.nan],
  1447. [np.nan, 0.1, np.nan, 0.3, 0.4, 0.5],
  1448. [0.5],
  1449. [np.nan, 0.7, 0.6],
  1450. ],
  1451. )
  1452. def test_rolling_quantile_interpolation_options(quantile, interpolation, data):
  1453. # Tests that rolling window's quantile behavior is analogous to
  1454. # Series' quantile for each interpolation option
  1455. s = Series(data)
  1456. q1 = s.quantile(quantile, interpolation)
  1457. q2 = s.expanding(min_periods=1).quantile(quantile, interpolation).iloc[-1]
  1458. if np.isnan(q1):
  1459. assert np.isnan(q2)
  1460. else:
  1461. assert q1 == q2
  1462. def test_invalid_quantile_value():
  1463. data = np.arange(5)
  1464. s = Series(data)
  1465. msg = "Interpolation 'invalid' is not supported"
  1466. with pytest.raises(ValueError, match=msg):
  1467. s.rolling(len(data), min_periods=1).quantile(0.5, interpolation="invalid")
  1468. def test_rolling_quantile_param():
  1469. ser = Series([0.0, 0.1, 0.5, 0.9, 1.0])
  1470. msg = "quantile value -0.1 not in \\[0, 1\\]"
  1471. with pytest.raises(ValueError, match=msg):
  1472. ser.rolling(3).quantile(-0.1)
  1473. msg = "quantile value 10.0 not in \\[0, 1\\]"
  1474. with pytest.raises(ValueError, match=msg):
  1475. ser.rolling(3).quantile(10.0)
  1476. msg = "must be real number, not str"
  1477. with pytest.raises(TypeError, match=msg):
  1478. ser.rolling(3).quantile("foo")
  1479. def test_rolling_std_1obs():
  1480. vals = Series([1.0, 2.0, 3.0, 4.0, 5.0])
  1481. result = vals.rolling(1, min_periods=1).std()
  1482. expected = Series([np.nan] * 5)
  1483. tm.assert_series_equal(result, expected)
  1484. result = vals.rolling(1, min_periods=1).std(ddof=0)
  1485. expected = Series([0.0] * 5)
  1486. tm.assert_series_equal(result, expected)
  1487. result = Series([np.nan, np.nan, 3, 4, 5]).rolling(3, min_periods=2).std()
  1488. assert np.isnan(result[2])
  1489. def test_rolling_std_neg_sqrt():
  1490. # unit test from Bottleneck
  1491. # Test move_nanstd for neg sqrt.
  1492. a = Series(
  1493. [
  1494. 0.0011448196318903589,
  1495. 0.00028718669878572767,
  1496. 0.00028718669878572767,
  1497. 0.00028718669878572767,
  1498. 0.00028718669878572767,
  1499. ]
  1500. )
  1501. b = a.rolling(window=3).std()
  1502. assert np.isfinite(b[2:]).all()
  1503. b = a.ewm(span=3).std()
  1504. assert np.isfinite(b[2:]).all()
  1505. def test_step_not_integer_raises():
  1506. with pytest.raises(ValueError, match="step must be an integer"):
  1507. DataFrame(range(2)).rolling(1, step="foo")
  1508. def test_step_not_positive_raises():
  1509. with pytest.raises(ValueError, match="step must be >= 0"):
  1510. DataFrame(range(2)).rolling(1, step=-1)
  1511. @pytest.mark.parametrize(
  1512. ["values", "window", "min_periods", "expected"],
  1513. [
  1514. [
  1515. [20, 10, 10, np.inf, 1, 1, 2, 3],
  1516. 3,
  1517. 1,
  1518. [np.nan, 50, 100 / 3, 0, 40.5, 0, 1 / 3, 1],
  1519. ],
  1520. [
  1521. [20, 10, 10, np.nan, 10, 1, 2, 3],
  1522. 3,
  1523. 1,
  1524. [np.nan, 50, 100 / 3, 0, 0, 40.5, 73 / 3, 1],
  1525. ],
  1526. [
  1527. [np.nan, 5, 6, 7, 5, 5, 5],
  1528. 3,
  1529. 3,
  1530. [np.nan] * 3 + [1, 1, 4 / 3, 0],
  1531. ],
  1532. [
  1533. [5, 7, 7, 7, np.nan, np.inf, 4, 3, 3, 3],
  1534. 3,
  1535. 3,
  1536. [np.nan] * 2 + [4 / 3, 0] + [np.nan] * 4 + [1 / 3, 0],
  1537. ],
  1538. [
  1539. [5, 7, 7, 7, np.nan, np.inf, 7, 3, 3, 3],
  1540. 3,
  1541. 3,
  1542. [np.nan] * 2 + [4 / 3, 0] + [np.nan] * 4 + [16 / 3, 0],
  1543. ],
  1544. [
  1545. [5, 7] * 4,
  1546. 3,
  1547. 3,
  1548. [np.nan] * 2 + [4 / 3] * 6,
  1549. ],
  1550. [
  1551. [5, 7, 5, np.nan, 7, 5, 7],
  1552. 3,
  1553. 2,
  1554. [np.nan, 2, 4 / 3] + [2] * 3 + [4 / 3],
  1555. ],
  1556. ],
  1557. )
  1558. def test_rolling_var_same_value_count_logic(values, window, min_periods, expected):
  1559. # GH 42064.
  1560. expected = Series(expected)
  1561. sr = Series(values)
  1562. # With new algo implemented, result will be set to .0 in rolling var
  1563. # if sufficient amount of consecutively same values are found.
  1564. result_var = sr.rolling(window, min_periods=min_periods).var()
  1565. # use `assert_series_equal` twice to check for equality,
  1566. # because `check_exact=True` will fail in 32-bit tests due to
  1567. # precision loss.
  1568. # 1. result should be close to correct value
  1569. # non-zero values can still differ slightly from "truth"
  1570. # as the result of online algorithm
  1571. tm.assert_series_equal(result_var, expected)
  1572. # 2. zeros should be exactly the same since the new algo takes effect here
  1573. tm.assert_series_equal(expected == 0, result_var == 0)
  1574. # std should also pass as it's just a sqrt of var
  1575. result_std = sr.rolling(window, min_periods=min_periods).std()
  1576. tm.assert_series_equal(result_std, np.sqrt(expected))
  1577. tm.assert_series_equal(expected == 0, result_std == 0)
  1578. def test_rolling_mean_sum_floating_artifacts():
  1579. # GH 42064.
  1580. sr = Series([1 / 3, 4, 0, 0, 0, 0, 0])
  1581. r = sr.rolling(3)
  1582. result = r.mean()
  1583. assert (result[-3:] == 0).all()
  1584. result = r.sum()
  1585. assert (result[-3:] == 0).all()
  1586. def test_rolling_skew_kurt_floating_artifacts():
  1587. # GH 42064 46431
  1588. sr = Series([1 / 3, 4, 0, 0, 0, 0, 0])
  1589. r = sr.rolling(4)
  1590. result = r.skew()
  1591. assert (result[-2:] == 0).all()
  1592. result = r.kurt()
  1593. assert (result[-2:] == -3).all()
  1594. def test_numeric_only_frame(arithmetic_win_operators, numeric_only):
  1595. # GH#46560
  1596. kernel = arithmetic_win_operators
  1597. df = DataFrame({"a": [1], "b": 2, "c": 3})
  1598. df["c"] = df["c"].astype(object)
  1599. rolling = df.rolling(2, min_periods=1)
  1600. op = getattr(rolling, kernel)
  1601. result = op(numeric_only=numeric_only)
  1602. columns = ["a", "b"] if numeric_only else ["a", "b", "c"]
  1603. expected = df[columns].agg([kernel]).reset_index(drop=True).astype(float)
  1604. assert list(expected.columns) == columns
  1605. tm.assert_frame_equal(result, expected)
  1606. @pytest.mark.parametrize("kernel", ["corr", "cov"])
  1607. @pytest.mark.parametrize("use_arg", [True, False])
  1608. def test_numeric_only_corr_cov_frame(kernel, numeric_only, use_arg):
  1609. # GH#46560
  1610. df = DataFrame({"a": [1, 2, 3], "b": 2, "c": 3})
  1611. df["c"] = df["c"].astype(object)
  1612. arg = (df,) if use_arg else ()
  1613. rolling = df.rolling(2, min_periods=1)
  1614. op = getattr(rolling, kernel)
  1615. result = op(*arg, numeric_only=numeric_only)
  1616. # Compare result to op using float dtypes, dropping c when numeric_only is True
  1617. columns = ["a", "b"] if numeric_only else ["a", "b", "c"]
  1618. df2 = df[columns].astype(float)
  1619. arg2 = (df2,) if use_arg else ()
  1620. rolling2 = df2.rolling(2, min_periods=1)
  1621. op2 = getattr(rolling2, kernel)
  1622. expected = op2(*arg2, numeric_only=numeric_only)
  1623. tm.assert_frame_equal(result, expected)
  1624. @pytest.mark.parametrize("dtype", [int, object])
  1625. def test_numeric_only_series(arithmetic_win_operators, numeric_only, dtype):
  1626. # GH#46560
  1627. kernel = arithmetic_win_operators
  1628. ser = Series([1], dtype=dtype)
  1629. rolling = ser.rolling(2, min_periods=1)
  1630. op = getattr(rolling, kernel)
  1631. if numeric_only and dtype is object:
  1632. msg = f"Rolling.{kernel} does not implement numeric_only"
  1633. with pytest.raises(NotImplementedError, match=msg):
  1634. op(numeric_only=numeric_only)
  1635. else:
  1636. result = op(numeric_only=numeric_only)
  1637. expected = ser.agg([kernel]).reset_index(drop=True).astype(float)
  1638. tm.assert_series_equal(result, expected)
  1639. @pytest.mark.parametrize("kernel", ["corr", "cov"])
  1640. @pytest.mark.parametrize("use_arg", [True, False])
  1641. @pytest.mark.parametrize("dtype", [int, object])
  1642. def test_numeric_only_corr_cov_series(kernel, use_arg, numeric_only, dtype):
  1643. # GH#46560
  1644. ser = Series([1, 2, 3], dtype=dtype)
  1645. arg = (ser,) if use_arg else ()
  1646. rolling = ser.rolling(2, min_periods=1)
  1647. op = getattr(rolling, kernel)
  1648. if numeric_only and dtype is object:
  1649. msg = f"Rolling.{kernel} does not implement numeric_only"
  1650. with pytest.raises(NotImplementedError, match=msg):
  1651. op(*arg, numeric_only=numeric_only)
  1652. else:
  1653. result = op(*arg, numeric_only=numeric_only)
  1654. ser2 = ser.astype(float)
  1655. arg2 = (ser2,) if use_arg else ()
  1656. rolling2 = ser2.rolling(2, min_periods=1)
  1657. op2 = getattr(rolling2, kernel)
  1658. expected = op2(*arg2, numeric_only=numeric_only)
  1659. tm.assert_series_equal(result, expected)