IT Share you

python pandas 데이터 프레임, 값에 의한 전달 또는 참조에 의한 전달

shareyou 2020. 12. 12. 12:42
반응형

python pandas 데이터 프레임, 값에 의한 전달 또는 참조에 의한 전달


데이터 프레임을 함수에 전달하고 함수 내에서 수정하면 값에 의한 전달 또는 참조에 의한 전달입니까?

다음 코드를 실행합니다.

a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
def letgo(df):
    df = df.drop('b',axis=1)
letgo(a)

의 값은 a함수 호출 후에 변경되지 않습니다. 가치에 의한 전달이라는 의미입니까?

나는 또한 다음을 시도했다

xx = np.array([[1,2], [3,4]])
def letgo2(x):
    x[1,1] = 100
def letgo3(x):
    x = np.array([[3,3],[3,3]])

그것은 밝혀 letgo2()변화를 수행 xx하고 letgo3()있지 않습니다. 왜 이런가요?


짧은 대답은 Python은 항상 값으로 전달하지만 모든 Python 변수는 실제로 일부 객체에 대한 포인터이므로 때때로 참조에 의한 전달처럼 보입니다.

파이썬에서 모든 객체는 변경 가능하거나 변경 불가능합니다. 예를 들어, 목록, 사전, 모듈 및 Pandas 데이터 프레임은 변경 가능하며 정수, 문자열 및 튜플은 변경 불가능합니다. 변경 가능한 객체는 내부적으로 변경 될 수 있지만 (예 : 목록에 요소 추가) 변경 불가능한 객체는 변경할 수 없습니다.

처음에 말했듯이 모든 Python 변수를 객체에 대한 포인터로 생각할 수 있습니다. 함수에 변수를 전달할 때 함수 내의 변수 (포인터)는 항상 전달 된 변수 (포인터)의 복사본입니다. 따라서 내부 변수에 새로운 것을 할당하면 다른 개체를 가리키는 지역 변수. 이것은 변수가 가리키는 원래 객체를 변경 (변형)하지 않으며 외부 변수가 새 객체를 가리 키도록 만들지 않습니다. 이 시점에서 외부 변수는 여전히 원래 개체를 가리 키지 만 내부 변수는 새 개체를 가리 킵니다.

원래 객체를 변경하려면 (변경 가능한 데이터 유형에서만 가능) 로컬 변수에 완전히 새로운 값을 할당 하지 않고 객체를 변경하는 작업을 수행해야 합니다. 이 이유 letgo()letgo3()변경되지 않은 외부 항목을두고 있지만 letgo2()변경합니다 그것.

@ursan이 지적했듯이 letgo()대신 이와 같은 것을 사용 하면 가리키는 원래 객체를 변경 (변형) df하여 전역 a변수 를 통해 표시되는 값을 변경합니다 .

def letgo(df):
    df.drop('b', axis=1, inplace=True)

a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
letgo(a)  # will alter a

어떤 경우에는 실제로 직접 할당하지 않고 원래 변수를 완전히 비우고 새 데이터로 다시 채울 수 있습니다. 예를 들어 v, 가리키는 원래 객체 가 변경되어 v나중에 사용할 때 표시되는 데이터가 변경 됩니다.

def letgo3(x):
    x[:] = np.array([[3,3],[3,3]])

v = np.empty((2, 2))
letgo3(v)   # will alter v

내가 직접 할당하는 것이 아니라는 점에 유의하십시오 x. 의 전체 내부 범위에 무언가를 할당하고 x있습니다.

완전히 새로운 객체를 생성하고 외부에서 볼 수 있도록해야하는 경우 (때로는 Pandas의 경우) 두 가지 옵션이 있습니다. 'clean'옵션은 새 개체를 반환하는 것입니다. 예 :

def letgo(df):
    df = df.drop('b',axis=1)
    return df

a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
a = letgo(a)

또 다른 옵션은 함수 외부에 도달하여 전역 변수를 직접 변경하는 것입니다. 이것은 a새로운 객체를 가리 키도록 변경 되고 a나중에 참조하는 모든 함수 는 새로운 객체를 보게됩니다.

def letgo():
    global a
    a = a.drop('b',axis=1)

a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
letgo()   # will alter a!

Directly altering global variables is usually a bad idea, because anyone who reads your code will have a hard time figuring out how a got changed. (I generally use global variables for shared parameters used by many functions in a script, but I don't let them alter those global variables.)


The question isn't PBV vs. PBR. These names only cause confusion in a language like Python; they were invented for languages that work like C or like Fortran (as the quintessential PBV and PBR languages). It is true, but not enlightening, that Python always passes by value. The question here is whether the value itself is mutated or whether you get a new value. Pandas usually errs on the side of the latter.

http://nedbatchelder.com/text/names.html explains very well what Python's system of names is.


To add to @Mike Graham's answer, who pointed to a very good read:

In your case, what is important to remember is the difference between names and values. a, df, xx, x, are all names, but they refer to the same or different values at different points of your examples:

  • In the first example, letgo rebinds df to another value, because df.drop returns a new DataFrame unless you set the argument inplace = True (see doc). That means that the name df (local to the letgo function), which was referring to the value of a, is now referring to a new value, here the df.drop return value. The value a is referring to still exists and hasn't changed.

  • In the second example, letgo2 mutates x, without rebinding it, which is why xx is modified by letgo2. Unlike the previous example, here the local name x always refers to the value the name xx is referring to, and changes that value in place, which is why the value xx is referring to has changed.

  • In the third example, letgo3 rebinds x to a new np.array. That causes the name x, local to letgo3 and previously referring to the value of xx, to now refer to another value, the new np.array. The value xx is referring to hasn't changed.


Python is neither pass by value nor pass by reference. It is pass by assignment.

Supporting reference, the Python FAQ: https://docs.python.org/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference

IOW:

  1. If you pass an immutable value, changes to it do not change its value in the caller - because you are rebinding the name to a new object.
  2. If you pass a mutable value, changes made in the called function, also change the value in the caller, so long as you do not rebind that name to a new object. If you reassign the variable, creating a new object, that change and subsequent changes to the name are not seen in the caller.

So if you pass a list, and change its 0th value, that change is seen in both the called and the caller. But if you reassign the list with a new list, this change is lost. But if you slice the list and replace that with a new list, that change is seen in both the called and the caller.

EG:

def change_it(list_):
    # This change would be seen in the caller if we left it alone
    list_[0] = 28

    # This change is also seen in the caller, and replaces the above
    # change
    list_[:] = [1, 2]

    # This change is not seen in the caller.
    # If this were pass by reference, this change too would be seen in
    # caller.
    list_ = [3, 4]

thing = [10, 20]
change_it(thing)
# here, thing is [1, 2]

If you're a C fan, you can think of this as passing a pointer by value - not a pointer to a pointer to a value, just a pointer to a value.

HTH.


Here is the doc for drop:

Return new object with labels in requested axis removed.

So a new dataframe is created. The original has not changed.

But as for all objects in python, the data frame is passed to the function by reference.


you need to make 'a' global at the start of the function otherwise it is a local variable and does not change the 'a' in the main code.

참고URL : https://stackoverflow.com/questions/38895768/python-pandas-dataframe-is-it-pass-by-value-or-pass-by-reference

반응형