programing

Python Panda 데이터 프레임(값별 또는 참조별)

padding 2023. 7. 22. 09:30
반응형

Python Panda 데이터 프레임(값별 또는 참조별)

데이터 프레임을 함수에 전달하고 함수 내부에서 수정하면 값별로 전달합니까, 기준별로 전달합니까?

다음 코드를 실행합니다.

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 변수는 실제로 어떤 개체에 대한 포인터이기 때문에 때때로 참조별로 전달하는 것처럼 보인다는 것입니다.

Python에서 모든 개체는 가변 또는 비변형입니다. 예를 들어 목록, 딕트, 모듈 및 Pandas 데이터 프레임은 가변이고 int, 문자열 및 튜플은 불변입니다.가변 개체는 내부적으로 변경할 수 있지만(예: 목록에 요소 추가), 가변 개체는 변경할 수 없습니다.

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

원래 개체를 변경하려면(변량 데이터 유형에서만 가능) 로컬 변수에 완전히 새로운 값을 할당하지 않고 개체를 변경하는 작업을 수행해야 합니다.이것이 이유입니다.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.

완전히 새로운 개체를 만들어 외부에서 볼 수 있도록 만들어야 한다면 두 가지 방법이 있습니다(팬더의 경우도 있습니다).'정리' 옵션은 새 개체를 반환하는 것입니다. 예를 들어,

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!

글로벌 변수를 직접 변경하는 것은 대개 좋지 않은 생각입니다. 왜냐하면 당신의 코드를 읽는 사람은 누구나 방법을 이해하는 데 어려움을 겪을 것이기 때문입니다.a옷을갈습니다었입 (하는 공유 하는데, 하게 하지 (일반적으로 스크립트의 여러 함수에서 사용하는 공유 매개 변수에 글로벌 변수를 사용하지만 이러한 글로벌 변수는 변경하지 않습니다.)

@Mike Graham의 대답에 덧붙이자면, 그는 매우 좋은 책을 가리켰습니다.

여러분의 경우, 기억해야 할 중요한 것은 이름의 차이입니다.a,df,xx,x모두 이름이지만 예제의 다른 지점에서 동일하거나 다른 값을 나타냅니다.

  • 번째에서는, 첫번째예는서에,는서,letgo 묶다 df으로, 다른가치로, 하면냐왜.df.drop새 항목을 반환합니다.DataFrame를 하지 않는 한inplace = True(문서 참조).그 말은 그 이름이df:letgo즉을 가리켰습니다.a이제 새로운 가치를 언급하고 있습니다, 여기서.df.drop가】값 a여전히 존재하고 변하지 않은 것을 말합니다.

  • 에서는, 두번예제서는에째,는서,letgo2 를 일으키다 x 않고, 그을다묶않고그, 서래것지.xx에 의해 되었습니다.letgo2이전 예와 달리 여기서는 로컬 이름x항상 이름의 값을 참조합니다.xx참조하고 있으며, 제자리에서 그 을 변경합니다. 이것이 그 값이 있는 이유입니다.xx는 변경되었음을 나타냅니다.

  • 에서는, 세번째예에는서,는서,letgo3 묶다 xnp.array그것이 이름의 원인이 됩니다.x letgo3에서는 그고이 언급가 치한에의 .xx이제 다른 값, 새로운 값을 언급합니다.np.array »xx는 변경되지 않았습니다.

문제는 PBV 대 PBR이 아닙니다.이러한 이름은 Python과 같은 언어에서만 혼동을 일으킵니다. C 또는 Fortran처럼 작동하는 언어(본질적인 PBV 및 PBR 언어)를 위해 고안되었습니다.Python이 항상 가치를 무시한다는 것은 사실이지만, 계몽적이지는 않습니다.여기서 문제는 값 자체가 변형되는지 아니면 새로운 값을 얻는지 여부입니다.판다는 보통 후자 쪽에서 실수를 합니다.

http://nedbatchelder.com/text/names.html Python의 이름 체계가 무엇인지 매우 잘 설명합니다.

Python은 값을 전달하거나 참조를 전달하지 않습니다.그것은 과제물에 의해 통과됩니다.

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

IOW:

  1. 변경할 수 없는 값을 전달하는 경우 이름을 새 개체로 다시 바인딩하므로 변경된 값은 호출자에서 변경되지 않습니다.
  2. 변수 값을 전달하면 호출된 함수에서 변경된 내용이 호출자의 값도 변경됩니다. 단, 해당 이름을 새 개체로 다시 바인딩하지 않는 한 해당 값도 변경됩니다.변수를 재할당하고 새 개체를 만드는 경우 해당 변경 사항과 이후 이름의 변경 사항은 호출자에게 표시되지 않습니다.

따라서 목록을 전달하고 0번째 값을 변경하면 해당 변경 사항은 호출된 사람과 호출자 모두에서 볼 수 있습니다.그러나 목록을 새 목록으로 재할당하면 변경 내용이 손실됩니다.그러나 목록을 잘라내고 새 목록으로 바꾸면 해당 변경 내용이 호출자와 호출자 모두에서 나타납니다.

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]

C 팬이라면 포인터를 값으로 전달하는 것으로 생각할 수 있습니다. 값에 대한 포인터가 아니라 값에 대한 포인터일 뿐입니다.

HTH.

다음은 드랍을 위한 문서입니다.

요청한 축의 레이블이 제거된 새 개체를 반환합니다.

따라서 새로운 데이터 프레임이 생성됩니다.원본은 변경되지 않았습니다.

그러나 python의 모든 객체에 대해서는 데이터 프레임이 참조를 통해 함수로 전달됩니다.

함수 시작 시 'a'를 전역으로 만들어야 합니다. 그렇지 않으면 로컬 변수이며 주 코드의 'a'를 변경하지 않습니다.

단답:

  • 값기준:df2 = df.copy()
  • 기준: 참조기준:df2 = df

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

반응형