Передача пандам DataFrame по ссылке
Мой вопрос касается неизменности DataFrame панд, когда он передается по ссылке. Рассмотрим следующий код:
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
Я заинтригован, почему это так. Любые идеи будут оценены.
2 ответа
Проблема из-за этой строки:
df1 = df1.join(df2['C'], how='inner')
df1.join(df2['C'], how='inner')
возвращает новый фрейм данных После этой строки df1
больше не ссылается на тот же фрейм данных, что и аргумент, но на новый, потому что он был переназначен новому результату. Первый фрейм данных продолжает существовать без изменений. Это на самом деле не проблема панд, просто общий способ работы Python и большинства других языков.
Некоторые функции панд имеют inplace
аргумент, который будет делать то, что вы хотите, а операция соединения - нет. Если вам нужно изменить фрейм данных, вам придется вместо этого вернуть этот новый и переназначить его вне функции.
В 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)