为什么循环中对pandas DataFrame执行pd.get_dummies操作不生效?
Python变量引用与pandas操作的底层逻辑
核心本质:Python中的所有变量都是指向内存中实际对象的标签,不是对象本身,赋值操作=的本质是修改标签的指向,不会修改原内存对象的内容。
各类写法的效果拆解
1. 直接遍历赋值为什么无效
for df in dataset: df = pd.get_dummies(df, columns=['A', 'B','C'])
- 循环变量
df是临时生成的局部标签,每次迭代会先指向dataset中存储的对应DataFrame对象 pd.get_dummies默认会生成一个全新的DataFrame对象,df = 新对象只是把临时标签df的指向改成了新对象,既不会修改原内存对象的内容,也不会修改dataset列表里存储的引用,更不会修改df_train、df_test这两个原有标签的指向,所以原变量访问不到变化。- 加
df.copy()的写法同理,复制操作本身就生成新对象,赋值给临时标签和原对象完全无关。
2. 按索引修改dataset为什么达不到预期
for i in range(len(dataset)): df = dataset[i] dataset[i] = pd.get_dummies(df, columns=['A', 'B','C'])
这个写法其实已经修改了dataset列表中存储的引用,此时dataset[0]已经是转换后的新DataFrame,但你原来单独定义的df_train、df_test两个标签还是指向原来的旧对象,标签本身没有被重新赋值,所以直接访问df_train还是旧结果。
3. inplace=True为什么生效
for df in dataset: df.drop('A', axis=1, inplace = True)
inplace=True的作用是直接修改当前标签指向的内存对象本身的内容,不会生成新对象,也不需要修改标签的指向。循环变量df和原df_train/df_test指向同一个内存对象,修改对象内容后,所有指向这个对象的标签访问到的结果都会同步变化。
注意:pd.get_dummies本身没有提供inplace参数,它的设计逻辑就是必须返回新对象,所以无法用原地操作的方式修改原DataFrame。
循环实现的正确写法
如果不想单独对每个DataFrame赋值,可以修改完列表后把新引用重新绑定到原有变量名:
dataset = [df_train, df_test] for i in range(len(dataset)): dataset[i] = pd.get_dummies(dataset[i], columns=['A', 'B','C']) # 把列表中的新对象重新绑定到原有变量名 df_train, df_test = dataset
内容的提问来源于stack exchange,提问作者Brian FitzGibbon
相关产品推荐
相关产品推荐

