IT박스

왜 팬더에서 데이터 프레임의 사본을 만들어야합니까?

itboxs 2020. 7. 2. 08:05
반응형

왜 팬더에서 데이터 프레임의 사본을 만들어야합니까?


부모 데이터 프레임에서 하위 데이터 프레임을 선택할 때 일부 프로그래머가 .copy()방법을 사용하여 데이터 프레임의 복사본을 만드는 것을 알았습니다 .

왜 데이터 프레임의 복사본을 만들고 있습니까? 사본을 만들지 않으면 어떻게됩니까?


이것은 바울의 대답으로 확장됩니다. Pandas에서 DataFrame을 인덱싱하면 초기 DataFrame에 대한 참조가 반환됩니다. 따라서 하위 집합을 변경하면 초기 DataFrame이 변경됩니다. 따라서 초기 DataFrame이 변경되지 않도록하려면 복사본을 사용하고 싶을 것입니다. 다음 코드를 고려하십시오.

df = DataFrame({'x': [1,2]})
df_sub = df[0:1]
df_sub.x = -1
print(df)

당신은 얻을 것이다:

x
0 -1
1  2

대조적으로, 다음은 df를 변경하지 않은 채로 둡니다.

df_sub_copy = df[0:1].copy()
df_sub_copy.x = -1

복사하지 않으면 dataFrame을 다른 이름으로 할당하더라도 색인을 다른 곳에서 조작 할 수 있기 때문입니다.

예를 들면 다음과 같습니다.

df2 = df
func1(df2)
func2(df)

func1은 df2를 수정하여 df를 수정할 수 있으므로 다음을 피하십시오.

df2 = df.copy()
func1(df2)
func2(df)

복사 또는보기 반환은 인덱싱 종류에 따라 달라집니다.

팬더 문서는 다음과 같이 말합니다.

뷰와 사본 반환

데이터에 대한 뷰가 반환되는시기에 대한 규칙은 전적으로 NumPy에 따라 다릅니다. 인덱싱 작업에 레이블 배열 또는 부울 벡터가 포함될 때마다 결과가 복사됩니다. df.ix [3 : 6] 또는 df.ix [:, 'A']와 같은 단일 레이블 / 스칼라 인덱싱 및 슬라이싱을 사용하면 뷰가 반환됩니다.


기본 목적은 체인 인덱싱을 피하고를 제거하는 것 SettingWithCopyWarning입니다.

여기서 체인 인덱싱은 dfc['A'][0] = 111

문서는 뷰와 복사본반환 할 때 체인 인덱싱을 피해야한다고 말했다 . 다음은 해당 문서에서 약간 수정 된 예입니다.

In [1]: import pandas as pd

In [2]: dfc = pd.DataFrame({'A':['aaa','bbb','ccc'],'B':[1,2,3]})

In [3]: dfc
Out[3]:
    A   B
0   aaa 1
1   bbb 2
2   ccc 3

In [4]: aColumn = dfc['A']

In [5]: aColumn[0] = 111
SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

In [6]: dfc
Out[6]:
    A   B
0   111 1
1   bbb 2
2   ccc 3

Here the aColumn is a view and not a copy from the original DataFrame, so modifying aColumn will cause the original dfc be modified too. Next, if we index the row first:

In [7]: zero_row = dfc.loc[0]

In [8]: zero_row['A'] = 222
SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

In [9]: dfc
Out[9]:
    A   B
0   111 1
1   bbb 2
2   ccc 3

This time zero_row is a copy, so the original dfc is not modified.

From these two examples above, we see it's ambiguous whether or not you want to change the original DataFrame. This is especially dangerous if you write something like the following:

In [10]: dfc.loc[0]['A'] = 333
SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

In [11]: dfc
Out[11]:
    A   B
0   111 1
1   bbb 2
2   ccc 3

This time it didn't work at all. Here we wanted to change dfc, but we actually modified an intermediate value dfc.loc[0] that is a copy and is discarded immediately. It’s very hard to predict whether the intermediate value like dfc.loc[0] or dfc['A'] is a view or a copy, so it's not guaranteed whether or not original DataFrame will be updated. That's why chained indexing should be avoided, and pandas generates the SettingWithCopyWarning for this kind of chained indexing update.

Now is the use of .copy(). To eliminate the warning, make a copy to express your intention explicitly:

In [12]: zero_row_copy = dfc.loc[0].copy()

In [13]: zero_row_copy['A'] = 444 # This time no warning

Since you are modifying a copy, you know the original dfc will never change and you are not expecting it to change. Your expectation matches the behavior, then the SettingWithCopyWarning disappears.

Note, If you do want to modify the original DataFrame, the document suggests you use loc:

In [14]: dfc.loc[0,'A'] = 555

In [15]: dfc
Out[15]:
    A   B
0   555 1
1   bbb 2
2   ccc 3

In general it is safer to work on copies than on original data frames, except when you know that you won't be needing the original anymore and want to proceed with the manipulated version. Normally, you would still have some use for the original data frame to compare with the manipulated version, etc. Therefore, most people work on copies and merge at the end.

참고URL : https://stackoverflow.com/questions/27673231/why-should-i-make-a-copy-of-a-data-frame-in-pandas

반응형