Передача пандам 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)
Другие вопросы по тегам