Python 通过引用传递数据帧
我的问题是关于熊猫数据帧通过引用传递时的不变性。考虑下面的代码:Python 通过引用传递数据帧,python,pandas,dataframe,pass-by-reference,immutability,Python,Pandas,Dataframe,Pass By Reference,Immutability,我的问题是关于熊猫数据帧通过引用传递时的不变性。考虑下面的代码: import pandas as pd def foo(df1, df2): df1['B'] = 1 df1 = df1.join(df2['C'], how='inner') return() def main(argv = None): # Create DataFrames. df1 = pd.DataFrame(range(0,10,2), columns=['A'])
import pandas as pd
def foo(df1, df2):
df1['B'] = 1
df1 = df1.join(df2['C'], how='inner')
return()
def main(argv = None):
# Create DataFrames.
df1 = pd.DataFrame(range(0,10,2), columns=['A'])
df2 = pd.DataFrame(range(1,11,2), columns=['C'])
foo(df1, df2) # Pass df1 and df2 by reference.
print df1
return(0)
if __name__ == '__main__':
status = main()
sys.exit(status)
输出是
A B
0 0 1
1 2 1
2 4 1
3 6 1
4 8 1
而不是
A B C
0 0 1 1
1 2 1 3
2 4 1 5
3 6 1 7
4 8 1 9
事实上,如果foo被定义为
def foo(df1, df2):
df1 = df1.join(df2['C'], how='inner')
df1['B'] = 1
return()
(即,在另一个语句之前的“join”语句)则输出为
A
0 0
1 2
2 4
3 6
4 8
我很好奇为什么会这样。如果您有任何见解,我们将不胜感激。问题在于这一行:
df1 = df1.join(df2['C'], how='inner')
df1.join(df2['C'],how='inner')
返回一个新的数据帧。在这一行之后,df1
不再引用与参数相同的数据帧,而是引用一个新的数据帧,因为它已被重新分配给新的结果。第一个数据帧继续存在,未经修改。这不是一个真正的问题,只是python和大多数其他语言的一般工作方式
有些函数有一个
inplace
参数,可以执行您想要的操作,但是join操作没有。如果需要修改数据帧,则必须返回此新数据帧,并在函数外部重新分配它。问题是因为这一行:
df1 = df1.join(df2['C'], how='inner')
df1.join(df2['C'],how='inner')
返回一个新的数据帧。在这一行之后,df1
不再引用与参数相同的数据帧,而是引用一个新的数据帧,因为它已被重新分配给新的结果。第一个数据帧继续存在,未经修改。这不是一个真正的问题,只是python和大多数其他语言的一般工作方式
有些函数有一个
inplace
参数,可以执行您想要的操作,但是join操作没有。如果需要修改数据帧,则必须返回此新数据帧,并在函数外部重新分配它。Python没有“按值传递”与“按引用传递”之比——只有两种
如果您将函数更改为
def foo(df1, df2):
res = df1.join(df2['C'], how='inner')
res['B'] = 1
return res
然后,函数中的df1
,df2
将绑定到您发送的对象。join
(在本例中是一个新对象)的结果绑定到名称res
。您可以在不影响任何其他对象或绑定的情况下操作并返回它
在您的呼叫代码中,您可以只编写
print foo(df1, df2)
Python没有按值传递和按引用传递,只有 如果您将函数更改为
def foo(df1, df2):
res = df1.join(df2['C'], how='inner')
res['B'] = 1
return res
然后,函数中的df1
,df2
将绑定到您发送的对象。join
(在本例中是一个新对象)的结果绑定到名称res
。您可以在不影响任何其他对象或绑定的情况下操作并返回它
在您的呼叫代码中,您可以只编写
print foo(df1, df2)
顺便说一句,return不是一个函数,它只是一个语句,所以不需要在它后面加括号。这是我所知道的关于Python名称如何工作的最好的讨论。一旦你明白了这一点,你就会明白这种行为。谢谢@chthonicdaemon!顺便说一句,return不是一个函数,它只是一个语句,所以不需要在它后面加括号。这是我所知道的关于Python名称如何工作的最好的讨论。一旦你明白了这一点,你就会明白这种行为。谢谢@chthonicdaemon!谢谢@Jezzamon。这很有道理。谢谢@Jezzamon。这是有道理的。