BUG: .rolling().mean() returns all NaNs on re-execution, despite .copy() use (original) (raw)

Pandas version checks

Reproducible Example

import yfinance as yf import pandas as pd

Step 1: Getting the data

ticker = "AAPL"

data = yf.download(ticker, start="2020-01-01", end="2025-07-13", auto_adjust=True, progress=False)

Step 3: Reduce to "Close" and copy

data = data[["Close"]].copy() # Note the use of .copy()

Step 3: Calculate rolling averages

shortWindow = 20

NOTE: Re-running the following line (in e.g. a Jupyter notebook cell) results in a column full of NaNs.

data[f"SMA{shortWindow}"] = data["Close"].rolling(window=shortWindow).mean()

Issue Description

When running a simple rolling mean assignment on a copied DataFrame, the operation works as expected on first execution, but subsequent executions result in columns full of NaNs, even though .copy() was used explicitly to break view ties.

This behavior suggests that .rolling() or the assignment mechanism is not fully stateless or clean between executions, which violates expectations around .copy() providing safe memory isolation.

Expected Behavior

After using .copy() on the sliced DataFrame—data = data[['Close']].copy()—I expect the object to be fully decoupled from its original state, and for repeated assignments to data['SMA20'] = data['Close'].rolling(20).mean() to behave identically and reliably, regardless of how many times the line is executed.

Instead, the observed behaviour is as follows:

Confirmed Environment Behavior

This issue was tested in:

This confirms the issue is a regression introduced in Pandas 2.x. The behavior is reproducible across multiple environments and interfaces.

🔄 Update: Bug Persists Even with .copy() on the Input Series

I believe I have further confirmed that the issue is not due to view/copy ambiguity of the input data.

I tested the following pattern, using .copy() explicitly on the input Series before applying .rolling(), as shown below:

Create a clean copy of the 'Close' column

closeData = data["Close"].copy()

Assign rolling mean result to new column

data[f"SMA{shortWindow}"] = closeData.rolling(window=shortWindow).mean()

However, re-running this assignment line a second time still results in the SMA20 column being filled with NaNs. This happens even though closeData is a deep copy, isolated from any previous DataFrame state.

This suggests that:

The bug continues to occur in both:

This further supports the conclusion that the bug is environment-independent, and likely a regression in core Pandas 2.x logic for repeated rolling assignments.

Installed Versions

INSTALLED VERSIONS

commit : c888af6
python : 3.11.3
python-bits : 64
OS : Darwin
OS-release : 24.0.0
Version : Darwin Kernel Version 24.0.0: Mon Aug 12 20:51:54 PDT 2024; root:xnu-11215.1.10~2/RELEASE_ARM64_T6000
machine : arm64
processor : arm
byteorder : little
LC_ALL : None
LANG : en_GB.UTF-8
LOCALE : en_GB.UTF-8

pandas : 2.3.1
numpy : 2.3.1
pytz : 2025.2
dateutil : 2.9.0.post0
pip : 22.3.1
Cython : None
sphinx : None
IPython : 9.4.0
adbc-driver-postgresql: None
adbc-driver-sqlite : None
bs4 : 4.13.4
blosc : None
bottleneck : None
dataframe-api-compat : None
fastparquet : None
fsspec : None
html5lib : None
hypothesis : None
gcsfs : None
jinja2 : 3.1.6
lxml.etree : None
matplotlib : 3.10.3
numba : None
numexpr : None
odfpy : None
openpyxl : None
pandas_gbq : None
psycopg2 : None
pymysql : None
pyarrow : None
pyreadstat : None
pytest : None
python-calamine : None
pyxlsb : None
s3fs : None
scipy : None
sqlalchemy : None
tables : None
tabulate : None
xarray : None
xlrd : None
xlsxwriter : None
zstandard : None
tzdata : 2025.2
qtpy : None
pyqt5 : None