如何编写非纯函数实现pandas dataframe间单行移动且对外生效
问题原因
该问题是Python变量作用域规则和pandas操作特性共同导致的:
- Python函数的形参属于局部变量,你在函数内执行
source = source.drop(...)、destination = destination.append(...)这类赋值操作时,只是让函数内部的source、destination局部变量指向了新生成的DataFrame对象,并不会修改外部实参原本指向的对象地址。 - pandas默认的
drop、append操作都不会修改原对象,而是返回修改后的新对象,你没有把新对象传递回外部作用域,自然看不到外部变量发生变化。
解决方法
最符合pandas使用习惯的方案是让函数返回修改后的两个DataFrame,外部调用时接收返回值即可,修改后的代码如下:
def move_line(ind, source, destination): row = source.loc[ind] destination = destination.append(row) source = source.drop(index=ind) print('source inside function\n', source, '\n\n') print('destination inside function\n', destination, '\n\n') # 新增返回语句传递修改后的对象 return source, destination def main(): df = pd.DataFrame({'lower': ['a','b','c'], 'upper': ['A', 'B', 'C'], 'number': [1, 2, 3]}, index=['first', 'second', 'third']) empty = pd.DataFrame(columns=['lower', 'upper', 'number']) # 接收函数返回的修改后对象 df, empty = move_line('second', df, empty) print('source outside function\n', df, '\n\n') print('destination outside function\n', empty)
如果你希望用inplace修改的方式实现(不需要返回值),可以调整写法为:
def move_line(ind, source, destination): row = source.loc[ind] # 直接在原destination对象上追加行 destination.loc[ind] = row # drop操作设置inplace=True直接修改原source对象 source.drop(index=ind, inplace=True) print('source inside function\n', source, '\n\n') print('destination inside function\n', destination, '\n\n')
注:inplace操作在pandas中一般不推荐使用,容易引发意料之外的副作用。
内容的提问来源于stack exchange,提问作者jp_tibirosen
相关产品推荐
相关产品推荐

