The Pandas rolling_mean and rolling_std functions have been deprecated and replaced by a more general "rolling" framework. @elyase's example can be modified to:

import pandas as pd
import numpy as np
%matplotlib inline

# some sample data
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000)).cumsum()

#plot the time series
ts.plot(style='k--')

# calculate a 60 day rolling mean and plot
ts.rolling(window=60).mean().plot(style='k')

# add the 20 day rolling standard deviation:
ts.rolling(window=20).std().plot(style='b')

The rolling function supports a number of different window types, as documented here. A number of functions can be called on the rolling object, including var and other interesting statistics (skew, kurt, quantile, etc.). I've stuck with std since the plot is on the same graph as the mean, which makes more sense unit-wise.

Answer from sfjac on Stack Overflow
🌐
Pandas
pandas.pydata.org › pandas-docs › stable › reference › api › pandas.core.window.rolling.Rolling.var.html
pandas.core.window.rolling.Rolling.var — pandas 2.3.3 documentation
>>> s = pd.Series([5, 5, 6, 7, 5, 5, 5]) >>> s.rolling(3).var() 0 NaN 1 NaN 2 0.333333 3 1.000000 4 1.000000 5 1.333333 6 0.000000 dtype: float64
🌐
Intelpython
intelpython.github.io › sdc-doc › latest › _api_ref › pandas.core.window.Rolling.var.html
pandas.core.window.Rolling.var — Intel® Scalable Dataframe Compiler 0.1 documentation
import pandas as pd from numba import njit @njit def series_rolling_var(): series = pd.Series([4, 3, 5, 2, 6]) # Series of 4, 3, 5, 2, 6 out_series = series.rolling(3).var() return out_series # Expect series of NaN, NaN, 1.000000, 2.333333, 4.333333 print(series_rolling_var()) $ python ./series/rolling/series_rolling_var.py 0 NaN 1 NaN 2 1.000000 3 2.333333 4 4.333333 dtype: float64 · Calculate unbiased rolling variance.¶ ·
🌐
W3cubDocs
docs.w3cub.com › pandas~0.25 › reference › api › pandas.core.window.rolling.var
Rolling.var() - Pandas 0.25 - W3cubDocs
/pandas 0.25 · Rolling.var(self, ddof=1, *args, **kwargs) [source] Calculate unbiased rolling variance. Normalized by N-1 by default. This can be changed using the ddof argument. See also · Series.rolling · Calling object with Series data. DataFrame.rolling ·
🌐
Pandas
pandas.pydata.org › pandas-docs › stable › reference › api › pandas.core.window.rolling.Rolling.std.html
pandas.core.window.rolling.Rolling.std — pandas 2.3.3 documentation
Calculate the rolling standard deviation · Delta Degrees of Freedom. The divisor used in calculations is N - ddof, where N represents the number of elements
🌐
GitHub
github.com › pandas-dev › pandas › issues › 52407
BUG: Rolling variance is negative · Issue #52407 · pandas-dev/pandas
April 4, 2023 - import pandas as pd A = [0.00000000e+00, 0.00000000e+00, 3.16188252e-18, 2.95781651e-16, 2.23153542e-51, 0.00000000e+00, 0.00000000e+00, 5.39943432e-48, 1.38206260e-73, 0.00000000e+00] ts = pd.DataFrame(A) print(ts.rolling(window=3, center=True).var(ddof=1)) I am trying to compute a rolling variance and for some reasons, some of the values I obtain are negative.
Author: pandas-dev
Find elsewhere
🌐
Sling Academy
slingacademy.com › article › pandas-dataframe-calculate-the-rolling-weighted-window-variance
Pandas DataFrame: Calculate the rolling weighted window variance - Sling Academy
To calculate the weighted variance, we need to apply weights to our rolling window. Pandas does not natively support rolling weighted variance directly, but we can achieve this by combining the rolling method with apply, and customizing our function or using libraries like numpy.
🌐
Pandas
pandas.pydata.org › docs › dev › reference › window.html
Rolling window functions - Pandas - PyData |
For an overview, see Windowing operations · pandas.api.typing.Rolling instances are returned by .rolling calls: pandas.DataFrame.rolling() and pandas.Series.rolling(). pandas.api.typing.Expanding instances are returned by .expanding calls: pandas.DataFrame.expanding() and pandas.Series.ex...
🌐
Pandas
pandas.pydata.org › docs › reference › api › pandas.core.window.rolling.Window.var.html
pandas.core.window.rolling.Window.var — pandas 2.3.3 documentation
Calculate the rolling weighted window variance. Parameters: numeric_onlybool, default False · Include only float, int, boolean columns. Added in version 1.5.0. **kwargs · Keyword arguments to configure the SciPy weighted window type. Returns: Series or DataFrame · Return type is the same as the original object with np.float64 dtype. See also · pandas.Series.rolling ·
🌐
Pandas
pandas.pydata.org › pandas-docs › version › 0.23.3 › generated › pandas.core.window.Rolling.var.html
pandas.core.window.Rolling.var — pandas 0.23.3 documentation
Extending Pandas · Release Notes · Enter search terms or a module, class or function name. Rolling.var(ddof=1, *args, **kwargs)[source]¶ · Calculate unbiased rolling variance. Normalized by N-1 by default. This can be changed using the ddof argument. See also · Series.rolling ·
Top answer
1 of 3
1

If you know, given a series, how to compute the semi std - then you use .rolling().apply() with that function.

Using the definition from https://www.investopedia.com/terms/s/semideviation.asp

We cannot use the built-in std because we need to use the whole group average, but only compute deviations based on those observations in the group that are below the average.

Looks like we'll need to define the semi-deviation as a function:

import numpy as np

def semi_std(ser):
    average = np.nanmean(ser)
    r_below = ser[ser < average]
    return np.sqrt(1/len(r_below) * np.sum((average - r_below)**2))

x.rolling(window).apply(semi_std, raw=True)

# using raw=True speeds up the computation - this is applicable
# if the function works well with a numpy array instead of a Series
# also, if possible, investigate using numba.

I think for maximum robustness, probably add a condition that if len(r_below) == 0 then the result is 0 or NaN (it's a matter of definition - but 0 is probably the reasonable choice).

2 of 3
1

The solution is actually pretty simple if one knows how rolling windows work in Pandas. The trick here is to use the shift function on the dataframe first which shifts each row by one position so it becomes the last element of the previous row. Then we can do our rolling mean calculation without having any issues with type conversion etc.

import pandas as pd

from datetime import timedelta

df = pd.DataFrame(data=np.random.randn(5, 4), index=pd.date_range('1/1/2000', periods=5))

df.index = df.index + timedelta(days=10)

print(df)
Top answer
1 of 1
1

If you use pandas resampling it works. Note you need to define a column that meets requirements for resampling. This effectively makes Period column redundant. You can also look into rollup() as well. I've done an example of this as well.

df["ts"] = pd.to_datetime(df.date, unit="ms", utc=True)
df["Monthly Variance"] = df.groupby(["PERMNO"]).resample("M", on="ts")["RET"].transform("var")
df["Bi-Monthly Variance"] = df.groupby(["PERMNO"]).resample("2M", on="ts")["RET"].transform("var")
df["Quarterly Variance"] = df.groupby(["PERMNO"]).resample("Q", on="ts")["RET"].transform("var")
df["Yearly Variance"] = df.groupby(["PERMNO"]).resample("Y", on="ts")["RET"].transform("var")
df["Rolling Variance"] = df.rolling(10,on="ts")["RET"].var()

Only calculate latest data rather than whole data frame

dfsub = df[df["ts"]>=pd.to_datetime(Timestamp('2019-08-01 00:00:00'), unit="ms", utc=True)].copy()
df.loc[dfsub.index,"Bi-Monthly Variance"] = 0
df.loc[dfsub.index,"Bi-Monthly Variance"] = df.loc[dfsub.index,].groupby(["PERMNO"]).resample("2M", on="ts").transform("var")["RET"]
    date        Period  PERMNO  RET         SPREAD      ts                       Monthly Variance   Bi-Monthly Variance Quarterly Variance  Yearly Variance Rolling Variance
0   2019-03-19  2019-03 93436   -0.007496   0.037349    2019-03-19 00:00:00+00:00   0.000071    0.000071    0.000071    0.000268    NaN
1   2019-03-29  2019-03 93436   0.004450    0.020619    2019-03-29 00:00:00+00:00   0.000071    0.000071    0.000071    0.000268    NaN
2   2019-04-10  2019-04 93436   0.013771    0.020109    2019-04-10 00:00:00+00:00   0.000044    0.000448    0.000340    0.000268    NaN
3   2019-04-23  2019-04 93436   0.004377    0.038514    2019-04-23 00:00:00+00:00   0.000044    0.000448    0.000340    0.000268    NaN
4   2019-05-03  2019-05 93436   0.044777    0.053883    2019-05-03 00:00:00+00:00   0.000872    0.000448    0.000340    0.000268    NaN
5   2019-05-15  2019-05 93436   -0.001550   0.031920    2019-05-15 00:00:00+00:00   0.000872    0.000448    0.000340    0.000268    NaN
6   2019-05-28  2019-05 93436   -0.010124   0.038062    2019-05-28 00:00:00+00:00   0.000872    0.000448    0.000340    0.000268    NaN
7   2019-06-07  2019-06 93436   -0.007041   0.036093    2019-06-07 00:00:00+00:00   0.000106    0.000167    0.000340    0.000268    NaN
8   2019-06-19  2019-06 93436   0.007520    0.030354    2019-06-19 00:00:00+00:00   0.000106    0.000167    0.000340    0.000268    NaN
9   2019-07-01  2019-07 93436   0.016602    0.030137    2019-07-01 00:00:00+00:00   0.000033    0.000167    0.000374    0.000268    0.000261
10  2019-07-12  2019-07 93436   0.027158    0.023654    2019-07-12 00:00:00+00:00   0.000033    0.000167    0.000374    0.000268    0.000273
11  2019-07-24  2019-07 93436   0.018104    0.030640    2019-07-24 00:00:00+00:00   0.000033    0.000167    0.000374    0.000268    0.000275
12  2019-08-05  2019-08 93436   -0.025689   0.024769    2019-08-05 00:00:00+00:00   0.000118    0.000370    0.000374    0.000268    0.000410
13  2019-08-15  2019-08 93436   -0.018122   0.047317    2019-08-15 00:00:00+00:00   0.000118    0.000370    0.000374    0.000268    0.000475
14  2019-08-27  2019-08 93436   -0.004279   0.031929    2019-08-27 00:00:00+00:00   0.000118    0.000370    0.000374    0.000268    0.000284
15  2019-09-09  2019-09 93436   0.019081    0.019762    2019-09-09 00:00:00+00:00   0.000020    0.000370    0.000374    0.000268    0.000318
16  2019-09-19  2019-09 93436   0.012773    0.012661    2019-09-19 00:00:00+00:00   0.000020    0.000370    0.000374    0.000268    0.000308
17  2019-10-01  2019-10 93436   0.015859    0.028520    2019-10-01 00:00:00+00:00   0.000109    0.000214    0.000221    0.000268    0.000301
18  2019-10-11  2019-10 93436   0.012871    0.017301    2019-10-11 00:00:00+00:00   0.000109    0.000214    0.000221    0.000268    0.000304
19  2019-10-23  2019-10 93436   -0.003521   0.019057    2019-10-23 00:00:00+00:00   0.000109    0.000214    0.000221    0.000268    0.000304
20  2019-11-04  2019-11 93436   0.013278    0.041001    2019-11-04 00:00:00+00:00   0.000375    0.000214    0.000221    0.000268    0.000256
21  2019-11-14  2019-11 93436   0.009361    0.031874    2019-11-14 00:00:00+00:00   0.000375    0.000214    0.000221    0.000268    0.000236
22  2019-11-26  2019-11 93436   -0.022061   0.025680    2019-11-26 00:00:00+00:00   0.000375    0.000214    0.000221    0.000268    0.000214
23  2019-12-09  2019-12 93436   0.010837    0.027964    2019-12-09 00:00:00+00:00   0.000142    0.000142    0.000221    0.000268    0.000159
24  2019-12-19  2019-12 93436   0.027699    0.026103    2019-12-19 00:00:00+00:00   0.000142    0.000142    0.000221    0.000268    0.000185
🌐
DataCamp
campus.datacamp.com › courses › visualizing-time-series-data-in-python › summary-statistics-and-diagnostics
Display rolling averages | Python
# Compute the 52 weeks rolling mean of the co2_levels DataFrame ma = ____.rolling(window=____).____() # Compute the 52 weeks rolling standard deviation of the co2_levels DataFrame mstd = ____ # Add the upper bound column to the ma DataFrame ma['upper'] = ma['co2'] + (____ * ____) # Add the lower bound column to the ma DataFrame ma['lower'] = ma['co2'] - (____ * ____) # Plot the content of the ma DataFrame ax = ____(linewidth=0.8, fontsize=6) # Specify labels, legend, and show the plot ax.set_xlabel('Date', fontsize=10) ax.set_ylabel('CO2 levels in Mauai Hawaii', fontsize=10) ax.set_title('Rolling mean and variance of CO2 levels\nin Mauai Hawaii from 1958 to 2001', fontsize=10) plt.show()
🌐
Stack Overflow
stackoverflow.com › questions › 56081988 › pandas-calculating-rolling-variance-in-rank-order
python - pandas - calculating rolling variance in rank order - Stack Overflow
Further, I need to know the number of values used in this rolling variance. So the first row of my result will be: Copy(var[0.002604], 1) in column 3 (var[0.002604, 0.003255], 2) in column 6 · et cetera · What is a quick way to do this, ideally without the use of apply()? My suspicion is that this is impossible. python · pandas ·
🌐
Pandas
pandas.pydata.org › pandas-docs › version › 0.15.2 › computation.html
Computational tools — pandas 0.15.2 documentation
For working with time series data, a number of functions are provided for computing common moving or rolling statistics. Among these are count, sum, mean, median, correlation, variance, covariance, standard deviation, skewness, and kurtosis. All of these methods are in the pandas namespace, but otherwise they can be found in pandas.stats.moments.
🌐
GitHub
github.com › ajcr › rolling
GitHub - ajcr/rolling: Computationally efficient rolling window iterators for Python (sum, variance, min/max, etc.) · GitHub
My attention was first drawn to this algorithm by Jaime Fernandez del Rio's excellent talk The Secret Life Of Rolling Pandas. The algorithm is also described by Keegan Carruthers-Smith here, along with code examples. Median uses the indexable skiplist approach presented by Raymond Hettinger here. Var and Std use Welford's algorithm. I referred to the rolling variance implementation in pandas as well as an older edit of the Wikipedia page Algorithms for calculating variance.
Starred by 204 users
Forked by 6 users
Languages: Python