Pandas version checks

  • [X] I have checked that this issue has not already been reported.

  • [X] I have confirmed this bug exists on the latest version of pandas.

  • [ ] I have confirmed this bug exists on the main branch of pandas.

Reproducible Example

import pandas as pd

# init pandas DataFrame from dictionary
d = {'Labels': {0: {'id1': {'value': True}}}}
df = pd.DataFrame(data=d) # 'data=d.copy()' holds same result

# copy dataframe
df_copy = df.copy(deep=True)

# update Labels column using loc
df_copy["Labels"].loc[0]["id1"]["value"] = False

# print to see what has changed
print(df_copy)
print(df)
print(d)

Issue Description

Dataframe copy does not work as expected when changing the new dataframe with .loc function if the records that is changed is part of a dictionary. The original dataframe and dictionary are changed as well, when changes are applied to the new dataframe. The .copy() function should prevent this kind of behaviour.

Expected Behavior

I expect that both df and d in the code example are unaffected by the changes made to df_copy, since we are working with the .copy() functionality. This is the case for other data types (as suggested here, so I do not understand why this is different for dictionaries. I find it particularly interesting that the original dictionary is update as well if we use .loc on the pandas DataFrame.

When using the following code the dictionary is unaffected df = pd.DataFrame(data=copy.deepcopy(d)) , but the issue with the dataframes still remains.

Installed Versions

Replace this line with the output of pd.show_versions() INSTALLED VERSIONS ------------------ commit : 8dab54d6573f7186ff0c3b6364d5e4dd635ff3e7 python : 3.8.13.final.0 python-bits : 64 OS : Linux OS-release : 5.15.79.1-microsoft-standard-WSL2 Version : #1 SMP Wed Nov 23 01:01:46 UTC 2022 machine : x86_64 processor : x86_64 byteorder : little LC_ALL : None LANG : C.UTF-8 LOCALE : en_US.UTF-8 pandas : 1.5.2 numpy : 1.23.5 pytz : 2022.6 dateutil : 2.8.2 setuptools : 60.6.0 pip : 22.0.3 Cython : None pytest : 5.4.3 hypothesis : None sphinx : None blosc : None feather : None xlsxwriter : None lxml.etree : None html5lib : None pymysql : None psycopg2 : None jinja2 : 3.1.2 IPython : None pandas_datareader: None bs4 : 4.11.1 bottleneck : None brotli : None fastparquet : None fsspec : None gcsfs : None matplotlib : 3.6.2 numba : None numexpr : None odfpy : None openpyxl : None pandas_gbq : None pyarrow : None pyreadstat : None pyxlsb : None s3fs : None scipy : 1.9.3 snappy : None sqlalchemy : None tables : None tabulate : None xarray : None xlrd : None xlwt : None zstandard : None tzdata : None **Comment From: MarcoGorelli** thanks for the report, can confirm this reproduces **Comment From: phofl** This behaves as expected. The notes section explains this and the last example illustrates what this means: https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.copy.html