[python] [:] 대 iloc [:]로 할당하면 판다에서 다른 결과가 나오는 이유는 무엇입니까?

iloc팬더에서 사용하는 다른 인덱싱 방법과 혼동됩니다 .

1-d 데이터 프레임을 2-d 데이터 프레임으로 변환하려고한다고 가정 해 봅시다. 먼저 다음 1-d 데이터 프레임이 있습니다.

a_array = [1,2,3,4,5,6,7,8]
a_df = pd.DataFrame(a_array).T

그리고 크기를 2 차원 데이터 프레임으로 변환하려고합니다 2x4. 다음과 같이 2 차원 데이터 프레임을 사전 설정하여 시작합니다.

b_df = pd.DataFrame(columns=range(4),index=range(2))

그런 다음 for-loop를 사용하여 다음 코드 로 a_df(1-d)를 b_df(2-d)로 변환하는 데 도움이 됩니다.

for i in range(2):
    b_df.iloc[i,:] = a_df.iloc[0,i*4:(i+1)*4]

그것은 단지 나에게 다음과 같은 결과를 제공합니다

     0    1    2    3
0    1    2    3    4
1  NaN  NaN  NaN  NaN

하지만 변경하는 경우 b_df.iloc[i,:]b_df.iloc[i][:]. 결과는 다음과 같이 정확합니다.

   0  1  2  3
0  1  2  3  4
1  5  6  7  8

누구든지 .iloc[i,:]와 의 차이점 과 위의 예에서 .iloc[i][:].iloc[i][:]효과 가 있었는지 설명 할 수 있습니까 ?.iloc[i,:]



답변

사이에는 매우 큰 차이가 있습니다 series.iloc[:]series[:]다시 할당 할 때 와와 ( 있습니다. (i)loc할당하려는 항목이 양수인의 색인과 일치하는지 항상 확인합니다. 한편, [:]구문은 인덱스 정렬을 무시하고 기본 NumPy 배열에 할당합니다.

s = pd.Series(index=[0, 1, 2, 3], dtype='float')
s

0   NaN
1   NaN
2   NaN
3   NaN
dtype: float64

# Let's get a reference to the underlying array with `copy=False`
arr = s.to_numpy(copy=False)
arr
# array([nan, nan, nan, nan])

# Reassign using slicing syntax
s[:] = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
s

0    1
1    2
2    3
3    4
dtype: int64

arr
# array([1., 2., 3., 4.]) # underlying array has changed

# Now, reassign again with `iloc`
s.iloc[:] = pd.Series([5, 6, 7, 8], index=[3, 4, 5, 6])
s

0    NaN
1    NaN
2    NaN
3    5.0
dtype: float64

arr
# array([1., 2., 3., 4.])  # `iloc` created a new array for the series
                           # during reassignment leaving this unchanged

s.to_numpy(copy=False)     # the new underlying array, for reference                                                   
# array([nan, nan, nan,  5.]) 

차이점을 이해 했으므로 코드에서 어떤 일이 발생하는지 살펴 보겠습니다. 루프의 RHS를 인쇄하여 할당 대상을 확인하십시오.

for i in range(2):
    print(a_df.iloc[0, i*4:(i+1)*4])

# output - first row                                                                   
0    1
1    2
2    3
3    4
Name: 0, dtype: int64
# second row. Notice the index is different
4    5
5    6
6    7
7    8
Name: 0, dtype: int64   

b_df.iloc[i, :]두 번째 반복에서 할당 할 때 인덱스가 다르므로 할당 된 것이 없으며 NaN 만 표시됩니다. 그러나 변경 b_df.iloc[i, :]하려면 b_df.iloc[i][:]색인 정렬이 바이 패스 있도록, 기본 NumPy와 배열에 할당 의미합니다. 이 작업은 다음과 같이 더 잘 표현됩니다.

for i in range(2):
    b_df.iloc[i, :] = a_df.iloc[0, i*4:(i+1)*4].to_numpy()

b_df

   0  1  2  3
0  1  2  3  4
1  5  6  7  8

또한 이것이 일종의 체인 할당이라는 것을 언급 할 가치 가 있으며, 이는 좋은 일이 아니며 코드를 읽고 이해하기 어렵게 만듭니다.


답변

차이점은 첫 번째 경우 Python 인터프리터가 코드를 다음과 같이 실행한다는 것입니다.

b_df.iloc[i,:] = a_df.iloc[0,i*4:(i+1)*4]
#as
b_df.iloc.__setitem__((i, slice(None)), value)

여기서 값은 방정식의 오른쪽입니다. 두 번째 경우에는 파이썬 인터프리터가 코드를 다음과 같이 실행했습니다.

b_df.iloc[i][:] = a_df.iloc[0,i*4:(i+1)*4]
#as
b_df.iloc.__getitem__(i).__setitem__(slice(None), value)

다시 값은 방정식의 오른쪽입니다.

이 두 경우 각각 키 (i, slice (None))와 slice (None)의 차이로 인해 setitem 내에서 다른 메소드가 호출 되므로 동작이 다릅니다.


답변

사람이 나에게 무엇의 차이를 설명 할 수 .iloc[i,:]
.iloc[i][:]입니다

차이점 .iloc[i,:].iloc[i][:]

의 ( ) 열을 모두 선택하여 .iloc[i,:]의 특정 위치에 직접 액세스 하는 경우DataFrame:i 번째 행 . 내가 아는 한, 2 차원을 지정하지 않은 상태 (.iloc[i] ) .

.iloc[i][:]2 개의 체인 작업을 수행하는 경우 . 따라서의 결과는의 .iloc[i]영향을받습니다 [:]. 이 값을 사용하여 값을 설정하는 것은 Pandas 자체 에서 경고와 함께 권장하지 않으므로 사용해서는 안됩니다.

설정 조작에 대해 사본 또는 참조가 리턴되는지 여부는 컨텍스트에 따라 달라질 수 있습니다. 이를 체인 할당이라고도하며 피해야합니다


… 그리고 왜 .iloc[i][:]위의 예에서 효과가 있었습니까?.iloc[i,:]

OP 주석에서 @Scott이 언급했듯이 데이터 정렬은 본질적 이므로 =왼쪽에없는 경우 오른쪽의 인덱스는 포함되지 않습니다. 이것이 이유입니다NaN 두 번째 행에 값 입니다.

따라서 일을 명확하게하기 위해 다음과 같이 할 수 있습니다.

for i in range(2):
    # Get the slice
    a_slice = a_df.iloc[0, i*4:(i+1)*4]
    # Reset the indices
    a_slice.reset_index(drop=True, inplace=True)
    # Set the slice into b_df
    b_df.iloc[i,:] = a_slice

또는 다음 list을 사용 하는 대신 로 변환 할 수 있습니다 reset_index.

for i in range(2):
    # Get the slice
    a_slice = a_df.iloc[0, i*4:(i+1)*4]
    # Convert the slice into a list and set it into b_df
    b_df.iloc[i,:] = list(a_slice)


답변