使用Pandas时如何在函数中保持原DataFrame不被修改?
解决Pandas函数中修改DataFrame时不影响原数据的问题
我来帮你梳理下问题所在,以及怎么实现「生成新DataFrame同时保留原数据」的需求:
问题根源
Pandas的DataFrame是引用类型,当你把df传入函数时,函数里的df_fn其实是指向原DataFrame的引用,并非独立的副本。这就导致直接操作df_fn会影响原数据;而链式索引的赋值又因为Pandas的内部机制,实际修改的是临时副本,所以完全没生效。
分析你的两种尝试:
链式索引赋值(
df_fn[cols][df_fn.fuel_type != 'gas'] = np.nan)
这种写法属于Pandas里的「链式索引」,会触发SettingWithCopyWarning(你可能没开启警告显示,但它确实存在)。这里的df_fn[cols]会返回一个临时副本,后续的赋值操作其实是修改这个副本,而非原DataFrame或函数里的df_fn,所以最终原df和返回的new_df都没变化。.loc索引赋值(
df_fn.loc[df_fn.fuel_type != 'gas', cols] = np.nan).loc是Pandas推荐的安全索引方式,它直接修改的是df_fn指向的原DataFrame对象,所以原df和new_df都会被修改——因为它们指向同一个内存地址的数据源。
正确解决方案:在函数内部创建深拷贝
要实现「修改后返回新DataFrame,原数据不受影响」,你需要在函数内部先对传入的DataFrame做深拷贝,然后操作这个拷贝后的独立对象,最后返回它。
修改后的代码如下:
import pandas as pd import numpy as np df = pd.DataFrame({'n_wheels': [2, 4, 4], 'color': ['red', 'blue', 'red'], 'year': [2010, 1990, 1999], 'fuel_type': ['diesel', 'gas', 'electric']}) print('原df = \n', df) def fn(df_input): # 先创建深拷贝,彻底断开与原数据的引用关联 df_fn = df_input.copy(deep=True) cols = ['n_wheels', 'color', 'year'] df_fn.loc[df_fn.fuel_type != 'gas', cols] = np.nan return df_fn new_df = fn(df) print('修改后的原df = \n', df) print('新生成的new_df = \n', new_df)
输出结果:
原df = n_wheels color year fuel_type 0 2 red 2010 diesel 1 4 blue 1990 gas 2 4 red 1999 electric 修改后的原df = n_wheels color year fuel_type 0 2 red 2010 diesel 1 4 blue 1990 gas 2 4 red 1999 electric 新生成的new_df = n_wheels color year fuel_type 0 NaN NaN NaN diesel 1 4.0 blue 1990.0 gas 2 NaN NaN NaN electric
补充说明
copy(deep=True)是深拷贝,会复制DataFrame的所有数据、索引和嵌套对象,生成完全独立的新对象;如果用浅拷贝(deep=False),对于包含复杂嵌套结构的DataFrame,可能还是会有引用共享的问题,所以推荐默认用深拷贝。- 永远优先使用
.loc/.iloc这类显式索引方式修改数据,避免链式索引带来的意外赋值失效问题。
内容的提问来源于stack exchange,提问作者zjzjzj
相关产品推荐
相关产品推荐

