expanding.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. from __future__ import annotations
  2. from textwrap import dedent
  3. from typing import (
  4. TYPE_CHECKING,
  5. Any,
  6. Callable,
  7. )
  8. from pandas._typing import (
  9. Axis,
  10. QuantileInterpolation,
  11. WindowingRankType,
  12. )
  13. if TYPE_CHECKING:
  14. from pandas import DataFrame, Series
  15. from pandas.core.generic import NDFrame
  16. from pandas.util._decorators import doc
  17. from pandas.core.indexers.objects import (
  18. BaseIndexer,
  19. ExpandingIndexer,
  20. GroupbyIndexer,
  21. )
  22. from pandas.core.window.doc import (
  23. _shared_docs,
  24. create_section_header,
  25. kwargs_numeric_only,
  26. numba_notes,
  27. template_header,
  28. template_returns,
  29. template_see_also,
  30. window_agg_numba_parameters,
  31. window_apply_parameters,
  32. )
  33. from pandas.core.window.rolling import (
  34. BaseWindowGroupby,
  35. RollingAndExpandingMixin,
  36. )
  37. class Expanding(RollingAndExpandingMixin):
  38. """
  39. Provide expanding window calculations.
  40. Parameters
  41. ----------
  42. min_periods : int, default 1
  43. Minimum number of observations in window required to have a value;
  44. otherwise, result is ``np.nan``.
  45. axis : int or str, default 0
  46. If ``0`` or ``'index'``, roll across the rows.
  47. If ``1`` or ``'columns'``, roll across the columns.
  48. For `Series` this parameter is unused and defaults to 0.
  49. method : str {'single', 'table'}, default 'single'
  50. Execute the rolling operation per single column or row (``'single'``)
  51. or over the entire object (``'table'``).
  52. This argument is only implemented when specifying ``engine='numba'``
  53. in the method call.
  54. .. versionadded:: 1.3.0
  55. Returns
  56. -------
  57. ``Expanding`` subclass
  58. See Also
  59. --------
  60. rolling : Provides rolling window calculations.
  61. ewm : Provides exponential weighted functions.
  62. Notes
  63. -----
  64. See :ref:`Windowing Operations <window.expanding>` for further usage details
  65. and examples.
  66. Examples
  67. --------
  68. >>> df = pd.DataFrame({"B": [0, 1, 2, np.nan, 4]})
  69. >>> df
  70. B
  71. 0 0.0
  72. 1 1.0
  73. 2 2.0
  74. 3 NaN
  75. 4 4.0
  76. **min_periods**
  77. Expanding sum with 1 vs 3 observations needed to calculate a value.
  78. >>> df.expanding(1).sum()
  79. B
  80. 0 0.0
  81. 1 1.0
  82. 2 3.0
  83. 3 3.0
  84. 4 7.0
  85. >>> df.expanding(3).sum()
  86. B
  87. 0 NaN
  88. 1 NaN
  89. 2 3.0
  90. 3 3.0
  91. 4 7.0
  92. """
  93. _attributes: list[str] = ["min_periods", "axis", "method"]
  94. def __init__(
  95. self,
  96. obj: NDFrame,
  97. min_periods: int = 1,
  98. axis: Axis = 0,
  99. method: str = "single",
  100. selection=None,
  101. ) -> None:
  102. super().__init__(
  103. obj=obj,
  104. min_periods=min_periods,
  105. axis=axis,
  106. method=method,
  107. selection=selection,
  108. )
  109. def _get_window_indexer(self) -> BaseIndexer:
  110. """
  111. Return an indexer class that will compute the window start and end bounds
  112. """
  113. return ExpandingIndexer()
  114. @doc(
  115. _shared_docs["aggregate"],
  116. see_also=dedent(
  117. """
  118. See Also
  119. --------
  120. pandas.DataFrame.aggregate : Similar DataFrame method.
  121. pandas.Series.aggregate : Similar Series method.
  122. """
  123. ),
  124. examples=dedent(
  125. """
  126. Examples
  127. --------
  128. >>> df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]})
  129. >>> df
  130. A B C
  131. 0 1 4 7
  132. 1 2 5 8
  133. 2 3 6 9
  134. >>> df.ewm(alpha=0.5).mean()
  135. A B C
  136. 0 1.000000 4.000000 7.000000
  137. 1 1.666667 4.666667 7.666667
  138. 2 2.428571 5.428571 8.428571
  139. """
  140. ),
  141. klass="Series/Dataframe",
  142. axis="",
  143. )
  144. def aggregate(self, func, *args, **kwargs):
  145. return super().aggregate(func, *args, **kwargs)
  146. agg = aggregate
  147. @doc(
  148. template_header,
  149. create_section_header("Returns"),
  150. template_returns,
  151. create_section_header("See Also"),
  152. template_see_also[:-1],
  153. window_method="expanding",
  154. aggregation_description="count of non NaN observations",
  155. agg_method="count",
  156. )
  157. def count(self, numeric_only: bool = False):
  158. return super().count(numeric_only=numeric_only)
  159. @doc(
  160. template_header,
  161. create_section_header("Parameters"),
  162. window_apply_parameters,
  163. create_section_header("Returns"),
  164. template_returns,
  165. create_section_header("See Also"),
  166. template_see_also[:-1],
  167. window_method="expanding",
  168. aggregation_description="custom aggregation function",
  169. agg_method="apply",
  170. )
  171. def apply(
  172. self,
  173. func: Callable[..., Any],
  174. raw: bool = False,
  175. engine: str | None = None,
  176. engine_kwargs: dict[str, bool] | None = None,
  177. args: tuple[Any, ...] | None = None,
  178. kwargs: dict[str, Any] | None = None,
  179. ):
  180. return super().apply(
  181. func,
  182. raw=raw,
  183. engine=engine,
  184. engine_kwargs=engine_kwargs,
  185. args=args,
  186. kwargs=kwargs,
  187. )
  188. @doc(
  189. template_header,
  190. create_section_header("Parameters"),
  191. kwargs_numeric_only,
  192. window_agg_numba_parameters(),
  193. create_section_header("Returns"),
  194. template_returns,
  195. create_section_header("See Also"),
  196. template_see_also,
  197. create_section_header("Notes"),
  198. numba_notes[:-1],
  199. window_method="expanding",
  200. aggregation_description="sum",
  201. agg_method="sum",
  202. )
  203. def sum(
  204. self,
  205. numeric_only: bool = False,
  206. engine: str | None = None,
  207. engine_kwargs: dict[str, bool] | None = None,
  208. ):
  209. return super().sum(
  210. numeric_only=numeric_only,
  211. engine=engine,
  212. engine_kwargs=engine_kwargs,
  213. )
  214. @doc(
  215. template_header,
  216. create_section_header("Parameters"),
  217. kwargs_numeric_only,
  218. window_agg_numba_parameters(),
  219. create_section_header("Returns"),
  220. template_returns,
  221. create_section_header("See Also"),
  222. template_see_also,
  223. create_section_header("Notes"),
  224. numba_notes[:-1],
  225. window_method="expanding",
  226. aggregation_description="maximum",
  227. agg_method="max",
  228. )
  229. def max(
  230. self,
  231. numeric_only: bool = False,
  232. engine: str | None = None,
  233. engine_kwargs: dict[str, bool] | None = None,
  234. ):
  235. return super().max(
  236. numeric_only=numeric_only,
  237. engine=engine,
  238. engine_kwargs=engine_kwargs,
  239. )
  240. @doc(
  241. template_header,
  242. create_section_header("Parameters"),
  243. kwargs_numeric_only,
  244. window_agg_numba_parameters(),
  245. create_section_header("Returns"),
  246. template_returns,
  247. create_section_header("See Also"),
  248. template_see_also,
  249. create_section_header("Notes"),
  250. numba_notes[:-1],
  251. window_method="expanding",
  252. aggregation_description="minimum",
  253. agg_method="min",
  254. )
  255. def min(
  256. self,
  257. numeric_only: bool = False,
  258. engine: str | None = None,
  259. engine_kwargs: dict[str, bool] | None = None,
  260. ):
  261. return super().min(
  262. numeric_only=numeric_only,
  263. engine=engine,
  264. engine_kwargs=engine_kwargs,
  265. )
  266. @doc(
  267. template_header,
  268. create_section_header("Parameters"),
  269. kwargs_numeric_only,
  270. window_agg_numba_parameters(),
  271. create_section_header("Returns"),
  272. template_returns,
  273. create_section_header("See Also"),
  274. template_see_also,
  275. create_section_header("Notes"),
  276. numba_notes[:-1],
  277. window_method="expanding",
  278. aggregation_description="mean",
  279. agg_method="mean",
  280. )
  281. def mean(
  282. self,
  283. numeric_only: bool = False,
  284. engine: str | None = None,
  285. engine_kwargs: dict[str, bool] | None = None,
  286. ):
  287. return super().mean(
  288. numeric_only=numeric_only,
  289. engine=engine,
  290. engine_kwargs=engine_kwargs,
  291. )
  292. @doc(
  293. template_header,
  294. create_section_header("Parameters"),
  295. kwargs_numeric_only,
  296. window_agg_numba_parameters(),
  297. create_section_header("Returns"),
  298. template_returns,
  299. create_section_header("See Also"),
  300. template_see_also,
  301. create_section_header("Notes"),
  302. numba_notes[:-1],
  303. window_method="expanding",
  304. aggregation_description="median",
  305. agg_method="median",
  306. )
  307. def median(
  308. self,
  309. numeric_only: bool = False,
  310. engine: str | None = None,
  311. engine_kwargs: dict[str, bool] | None = None,
  312. ):
  313. return super().median(
  314. numeric_only=numeric_only,
  315. engine=engine,
  316. engine_kwargs=engine_kwargs,
  317. )
  318. @doc(
  319. template_header,
  320. create_section_header("Parameters"),
  321. dedent(
  322. """
  323. ddof : int, default 1
  324. Delta Degrees of Freedom. The divisor used in calculations
  325. is ``N - ddof``, where ``N`` represents the number of elements.\n
  326. """
  327. ).replace("\n", "", 1),
  328. kwargs_numeric_only,
  329. window_agg_numba_parameters("1.4"),
  330. create_section_header("Returns"),
  331. template_returns,
  332. create_section_header("See Also"),
  333. "numpy.std : Equivalent method for NumPy array.\n",
  334. template_see_also,
  335. create_section_header("Notes"),
  336. dedent(
  337. """
  338. The default ``ddof`` of 1 used in :meth:`Series.std` is different
  339. than the default ``ddof`` of 0 in :func:`numpy.std`.
  340. A minimum of one period is required for the rolling calculation.\n
  341. """
  342. ).replace("\n", "", 1),
  343. create_section_header("Examples"),
  344. dedent(
  345. """
  346. >>> s = pd.Series([5, 5, 6, 7, 5, 5, 5])
  347. >>> s.expanding(3).std()
  348. 0 NaN
  349. 1 NaN
  350. 2 0.577350
  351. 3 0.957427
  352. 4 0.894427
  353. 5 0.836660
  354. 6 0.786796
  355. dtype: float64
  356. """
  357. ).replace("\n", "", 1),
  358. window_method="expanding",
  359. aggregation_description="standard deviation",
  360. agg_method="std",
  361. )
  362. def std(
  363. self,
  364. ddof: int = 1,
  365. numeric_only: bool = False,
  366. engine: str | None = None,
  367. engine_kwargs: dict[str, bool] | None = None,
  368. ):
  369. return super().std(
  370. ddof=ddof,
  371. numeric_only=numeric_only,
  372. engine=engine,
  373. engine_kwargs=engine_kwargs,
  374. )
  375. @doc(
  376. template_header,
  377. create_section_header("Parameters"),
  378. dedent(
  379. """
  380. ddof : int, default 1
  381. Delta Degrees of Freedom. The divisor used in calculations
  382. is ``N - ddof``, where ``N`` represents the number of elements.\n
  383. """
  384. ).replace("\n", "", 1),
  385. kwargs_numeric_only,
  386. window_agg_numba_parameters("1.4"),
  387. create_section_header("Returns"),
  388. template_returns,
  389. create_section_header("See Also"),
  390. "numpy.var : Equivalent method for NumPy array.\n",
  391. template_see_also,
  392. create_section_header("Notes"),
  393. dedent(
  394. """
  395. The default ``ddof`` of 1 used in :meth:`Series.var` is different
  396. than the default ``ddof`` of 0 in :func:`numpy.var`.
  397. A minimum of one period is required for the rolling calculation.\n
  398. """
  399. ).replace("\n", "", 1),
  400. create_section_header("Examples"),
  401. dedent(
  402. """
  403. >>> s = pd.Series([5, 5, 6, 7, 5, 5, 5])
  404. >>> s.expanding(3).var()
  405. 0 NaN
  406. 1 NaN
  407. 2 0.333333
  408. 3 0.916667
  409. 4 0.800000
  410. 5 0.700000
  411. 6 0.619048
  412. dtype: float64
  413. """
  414. ).replace("\n", "", 1),
  415. window_method="expanding",
  416. aggregation_description="variance",
  417. agg_method="var",
  418. )
  419. def var(
  420. self,
  421. ddof: int = 1,
  422. numeric_only: bool = False,
  423. engine: str | None = None,
  424. engine_kwargs: dict[str, bool] | None = None,
  425. ):
  426. return super().var(
  427. ddof=ddof,
  428. numeric_only=numeric_only,
  429. engine=engine,
  430. engine_kwargs=engine_kwargs,
  431. )
  432. @doc(
  433. template_header,
  434. create_section_header("Parameters"),
  435. dedent(
  436. """
  437. ddof : int, default 1
  438. Delta Degrees of Freedom. The divisor used in calculations
  439. is ``N - ddof``, where ``N`` represents the number of elements.\n
  440. """
  441. ).replace("\n", "", 1),
  442. kwargs_numeric_only,
  443. create_section_header("Returns"),
  444. template_returns,
  445. create_section_header("See Also"),
  446. template_see_also,
  447. create_section_header("Notes"),
  448. "A minimum of one period is required for the calculation.\n\n",
  449. create_section_header("Examples"),
  450. dedent(
  451. """
  452. >>> s = pd.Series([0, 1, 2, 3])
  453. >>> s.expanding().sem()
  454. 0 NaN
  455. 1 0.707107
  456. 2 0.707107
  457. 3 0.745356
  458. dtype: float64
  459. """
  460. ).replace("\n", "", 1),
  461. window_method="expanding",
  462. aggregation_description="standard error of mean",
  463. agg_method="sem",
  464. )
  465. def sem(self, ddof: int = 1, numeric_only: bool = False):
  466. return super().sem(ddof=ddof, numeric_only=numeric_only)
  467. @doc(
  468. template_header,
  469. create_section_header("Parameters"),
  470. kwargs_numeric_only,
  471. create_section_header("Returns"),
  472. template_returns,
  473. create_section_header("See Also"),
  474. "scipy.stats.skew : Third moment of a probability density.\n",
  475. template_see_also,
  476. create_section_header("Notes"),
  477. "A minimum of three periods is required for the rolling calculation.\n",
  478. window_method="expanding",
  479. aggregation_description="unbiased skewness",
  480. agg_method="skew",
  481. )
  482. def skew(self, numeric_only: bool = False):
  483. return super().skew(numeric_only=numeric_only)
  484. @doc(
  485. template_header,
  486. create_section_header("Parameters"),
  487. kwargs_numeric_only,
  488. create_section_header("Returns"),
  489. template_returns,
  490. create_section_header("See Also"),
  491. "scipy.stats.kurtosis : Reference SciPy method.\n",
  492. template_see_also,
  493. create_section_header("Notes"),
  494. "A minimum of four periods is required for the calculation.\n\n",
  495. create_section_header("Examples"),
  496. dedent(
  497. """
  498. The example below will show a rolling calculation with a window size of
  499. four matching the equivalent function call using `scipy.stats`.
  500. >>> arr = [1, 2, 3, 4, 999]
  501. >>> import scipy.stats
  502. >>> print(f"{{scipy.stats.kurtosis(arr[:-1], bias=False):.6f}}")
  503. -1.200000
  504. >>> print(f"{{scipy.stats.kurtosis(arr, bias=False):.6f}}")
  505. 4.999874
  506. >>> s = pd.Series(arr)
  507. >>> s.expanding(4).kurt()
  508. 0 NaN
  509. 1 NaN
  510. 2 NaN
  511. 3 -1.200000
  512. 4 4.999874
  513. dtype: float64
  514. """
  515. ).replace("\n", "", 1),
  516. window_method="expanding",
  517. aggregation_description="Fisher's definition of kurtosis without bias",
  518. agg_method="kurt",
  519. )
  520. def kurt(self, numeric_only: bool = False):
  521. return super().kurt(numeric_only=numeric_only)
  522. @doc(
  523. template_header,
  524. create_section_header("Parameters"),
  525. dedent(
  526. """
  527. quantile : float
  528. Quantile to compute. 0 <= quantile <= 1.
  529. interpolation : {{'linear', 'lower', 'higher', 'midpoint', 'nearest'}}
  530. This optional parameter specifies the interpolation method to use,
  531. when the desired quantile lies between two data points `i` and `j`:
  532. * linear: `i + (j - i) * fraction`, where `fraction` is the
  533. fractional part of the index surrounded by `i` and `j`.
  534. * lower: `i`.
  535. * higher: `j`.
  536. * nearest: `i` or `j` whichever is nearest.
  537. * midpoint: (`i` + `j`) / 2.
  538. """
  539. ).replace("\n", "", 1),
  540. kwargs_numeric_only,
  541. create_section_header("Returns"),
  542. template_returns,
  543. create_section_header("See Also"),
  544. template_see_also[:-1],
  545. window_method="expanding",
  546. aggregation_description="quantile",
  547. agg_method="quantile",
  548. )
  549. def quantile(
  550. self,
  551. quantile: float,
  552. interpolation: QuantileInterpolation = "linear",
  553. numeric_only: bool = False,
  554. ):
  555. return super().quantile(
  556. quantile=quantile,
  557. interpolation=interpolation,
  558. numeric_only=numeric_only,
  559. )
  560. @doc(
  561. template_header,
  562. ".. versionadded:: 1.4.0 \n\n",
  563. create_section_header("Parameters"),
  564. dedent(
  565. """
  566. method : {{'average', 'min', 'max'}}, default 'average'
  567. How to rank the group of records that have the same value (i.e. ties):
  568. * average: average rank of the group
  569. * min: lowest rank in the group
  570. * max: highest rank in the group
  571. ascending : bool, default True
  572. Whether or not the elements should be ranked in ascending order.
  573. pct : bool, default False
  574. Whether or not to display the returned rankings in percentile
  575. form.
  576. """
  577. ).replace("\n", "", 1),
  578. kwargs_numeric_only,
  579. create_section_header("Returns"),
  580. template_returns,
  581. create_section_header("See Also"),
  582. template_see_also,
  583. create_section_header("Examples"),
  584. dedent(
  585. """
  586. >>> s = pd.Series([1, 4, 2, 3, 5, 3])
  587. >>> s.expanding().rank()
  588. 0 1.0
  589. 1 2.0
  590. 2 2.0
  591. 3 3.0
  592. 4 5.0
  593. 5 3.5
  594. dtype: float64
  595. >>> s.expanding().rank(method="max")
  596. 0 1.0
  597. 1 2.0
  598. 2 2.0
  599. 3 3.0
  600. 4 5.0
  601. 5 4.0
  602. dtype: float64
  603. >>> s.expanding().rank(method="min")
  604. 0 1.0
  605. 1 2.0
  606. 2 2.0
  607. 3 3.0
  608. 4 5.0
  609. 5 3.0
  610. dtype: float64
  611. """
  612. ).replace("\n", "", 1),
  613. window_method="expanding",
  614. aggregation_description="rank",
  615. agg_method="rank",
  616. )
  617. def rank(
  618. self,
  619. method: WindowingRankType = "average",
  620. ascending: bool = True,
  621. pct: bool = False,
  622. numeric_only: bool = False,
  623. ):
  624. return super().rank(
  625. method=method,
  626. ascending=ascending,
  627. pct=pct,
  628. numeric_only=numeric_only,
  629. )
  630. @doc(
  631. template_header,
  632. create_section_header("Parameters"),
  633. dedent(
  634. """
  635. other : Series or DataFrame, optional
  636. If not supplied then will default to self and produce pairwise
  637. output.
  638. pairwise : bool, default None
  639. If False then only matching columns between self and other will be
  640. used and the output will be a DataFrame.
  641. If True then all pairwise combinations will be calculated and the
  642. output will be a MultiIndexed DataFrame in the case of DataFrame
  643. inputs. In the case of missing elements, only complete pairwise
  644. observations will be used.
  645. ddof : int, default 1
  646. Delta Degrees of Freedom. The divisor used in calculations
  647. is ``N - ddof``, where ``N`` represents the number of elements.
  648. """
  649. ).replace("\n", "", 1),
  650. kwargs_numeric_only,
  651. create_section_header("Returns"),
  652. template_returns,
  653. create_section_header("See Also"),
  654. template_see_also[:-1],
  655. window_method="expanding",
  656. aggregation_description="sample covariance",
  657. agg_method="cov",
  658. )
  659. def cov(
  660. self,
  661. other: DataFrame | Series | None = None,
  662. pairwise: bool | None = None,
  663. ddof: int = 1,
  664. numeric_only: bool = False,
  665. ):
  666. return super().cov(
  667. other=other,
  668. pairwise=pairwise,
  669. ddof=ddof,
  670. numeric_only=numeric_only,
  671. )
  672. @doc(
  673. template_header,
  674. create_section_header("Parameters"),
  675. dedent(
  676. """
  677. other : Series or DataFrame, optional
  678. If not supplied then will default to self and produce pairwise
  679. output.
  680. pairwise : bool, default None
  681. If False then only matching columns between self and other will be
  682. used and the output will be a DataFrame.
  683. If True then all pairwise combinations will be calculated and the
  684. output will be a MultiIndexed DataFrame in the case of DataFrame
  685. inputs. In the case of missing elements, only complete pairwise
  686. observations will be used.
  687. """
  688. ).replace("\n", "", 1),
  689. kwargs_numeric_only,
  690. create_section_header("Returns"),
  691. template_returns,
  692. create_section_header("See Also"),
  693. dedent(
  694. """
  695. cov : Similar method to calculate covariance.
  696. numpy.corrcoef : NumPy Pearson's correlation calculation.
  697. """
  698. ).replace("\n", "", 1),
  699. template_see_also,
  700. create_section_header("Notes"),
  701. dedent(
  702. """
  703. This function uses Pearson's definition of correlation
  704. (https://en.wikipedia.org/wiki/Pearson_correlation_coefficient).
  705. When `other` is not specified, the output will be self correlation (e.g.
  706. all 1's), except for :class:`~pandas.DataFrame` inputs with `pairwise`
  707. set to `True`.
  708. Function will return ``NaN`` for correlations of equal valued sequences;
  709. this is the result of a 0/0 division error.
  710. When `pairwise` is set to `False`, only matching columns between `self` and
  711. `other` will be used.
  712. When `pairwise` is set to `True`, the output will be a MultiIndex DataFrame
  713. with the original index on the first level, and the `other` DataFrame
  714. columns on the second level.
  715. In the case of missing elements, only complete pairwise observations
  716. will be used.
  717. """
  718. ).replace("\n", "", 1),
  719. window_method="expanding",
  720. aggregation_description="correlation",
  721. agg_method="corr",
  722. )
  723. def corr(
  724. self,
  725. other: DataFrame | Series | None = None,
  726. pairwise: bool | None = None,
  727. ddof: int = 1,
  728. numeric_only: bool = False,
  729. ):
  730. return super().corr(
  731. other=other,
  732. pairwise=pairwise,
  733. ddof=ddof,
  734. numeric_only=numeric_only,
  735. )
  736. class ExpandingGroupby(BaseWindowGroupby, Expanding):
  737. """
  738. Provide a expanding groupby implementation.
  739. """
  740. _attributes = Expanding._attributes + BaseWindowGroupby._attributes
  741. def _get_window_indexer(self) -> GroupbyIndexer:
  742. """
  743. Return an indexer class that will compute the window start and end bounds
  744. Returns
  745. -------
  746. GroupbyIndexer
  747. """
  748. window_indexer = GroupbyIndexer(
  749. groupby_indices=self._grouper.indices,
  750. window_indexer=ExpandingIndexer,
  751. )
  752. return window_indexer