iloc, ix 및 loc은 어떻게 다른가요?


636

누군가이 세 가지 슬라이스 방법이 어떻게 다른지 설명 할 수 있습니까?
나는 문서를 보았고 이러한 답변 을 보았지만 여전히 세 가지가 어떻게 다른지 설명 할 수 없다고 생각합니다. 나에게, 그들은 낮은 수준의 슬라이싱에 있기 때문에 대체로 상호 교환 가능한 것처럼 보입니다.

예를 들어의 첫 5 개 행을 가져오고 싶다고 가정 해 보겠습니다 DataFrame. 이 세 가지가 모두 어떻게 작동합니까?

df.loc[:5]
df.ix[:5]
df.iloc[:5]

누군가 사용의 구별이 더 명확한 세 가지 경우를 제시 할 수 있습니까?


7
SettingWithCopyWarning 시나리오를 언급하는 것이 매우 중요합니다 : stackoverflow.com/questions/20625582/…stackoverflow.com/questions/23688307/…
Paul

9
ix는 이제 지원 중단 예정입니다 : github.com/pandas-dev/pandas/issues/14218
JohnE

답변:


969

참고 : 팬더 버전 0.20.0 이상으로 ix되어 사용되지 않는 및 사용 loc과는 iloc대신 권장합니다. 필자는 ix이전 버전의 팬더 사용자를위한 참조로 그대로 설명하는이 답변의 일부를 남겼습니다 . 에 대한 대안을 보여주는 예가 아래에 추가되었습니다 ix .


먼저 다음 세 가지 방법을 살펴 보겠습니다.

  • loc인덱스에서 특정 레이블 이있는 행 (또는 열)을 가져옵니다.
  • iloc인덱스의 특정 위치 에서 행 (또는 열)을 가져옵니다 (정수만 사용).
  • ix일반적으로 동작을 시도 loc하지만 iloc색인에 레이블이없는 경우 처럼 동작 합니다.

ix사용하기 약간 까다로울 수있는 몇 가지 미묘한 점에 주목하는 것이 중요 합니다.

  • 색인이 정수 유형 인 ix경우 레이블 기반 색인 만 사용하고 위치 기반 색인으로 돌아 가지 않습니다. 레이블이 색인에 없으면 오류가 발생합니다.

  • 인덱스에 정수만 포함되어 있지 않은 경우 정수가 지정된 ix경우 레이블 기반 인덱싱 대신 위치 기반 인덱싱을 즉시 사용합니다. 그러나 ix다른 유형 (예 : 문자열)이 제공되면 레이블 기반 색인 작성을 사용할 수 있습니다.


세 가지 방법의 차이점을 설명하기 위해 다음 시리즈를 고려하십시오.

>>> s = pd.Series(np.nan, index=[49,48,47,46,45, 1, 2, 3, 4, 5])
>>> s
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN
4    NaN
5    NaN

정수 값으로 슬라이싱을 살펴 보겠습니다 3.

이 경우 s.iloc[:3]처음 3 개 행을 반환하고 (3을 위치로 취급하므로) s.loc[:3]처음 8 개 행을 반환합니다 (3을 레이블로 취급하므로).

>>> s.iloc[:3] # slice the first three rows
49   NaN
48   NaN
47   NaN

>>> s.loc[:3] # slice up to and including label 3
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN

>>> s.ix[:3] # the integer is in the index so s.ix[:3] works like loc
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN

통지 s.ix[:3]s.loc[:3]위치에서 작업하기보다는 레이블을 먼저 찾기 때문에 (그리고 인덱스 s는 정수 유형 임) 동일한 시리즈를 반환합니다 .

인덱스에없는 정수 레이블로 시도하면 어떻게 6되나요?

여기서 s.iloc[:6]예상대로 Series의 처음 6 행을 반환합니다. 그러나 인덱스에 없기 s.loc[:6]때문에 KeyError 6가 발생합니다.

>>> s.iloc[:6]
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN

>>> s.loc[:6]
KeyError: 6

>>> s.ix[:6]
KeyError: 6

위에서 언급 한 미묘함에 따라 s.ix[:6]이제는 KeyError처럼 작동하려고 loc하지만 6인덱스에서 찾을 수 없기 때문에 KeyError가 발생합니다 . 우리의 인덱스는 정수 타입이기 때문에 ix처럼 동작하지 않습니다 iloc.

그러나 인덱스가 혼합 유형 인 경우 KeyError를 발생시키는 대신 정수 ixiloc즉시 작동합니다 .

>>> s2 = pd.Series(np.nan, index=['a','b','c','d','e', 1, 2, 3, 4, 5])
>>> s2.index.is_mixed() # index is mix of different types
True
>>> s2.ix[:6] # now behaves like iloc given integer
a   NaN
b   NaN
c   NaN
d   NaN
e   NaN
1   NaN

명심 ix여전히 같은 비 정수와 행동하라를 받아 들일 수 loc:

>>> s2.ix[:'c'] # behaves like loc given non-integer
a   NaN
b   NaN
c   NaN

일반적으로 레이블을 사용하여 인덱싱하거나 정수 위치를 사용하여 인덱싱하는 경우 예기치 않은 결과를 피 loc하거나 iloc피하려면 사용하지 마십시오 ix.


위치 기반 및 라벨 기반 색인 생성

때로는 DataFrame이 주어지면 행과 열에 대해 레이블 및 위치 인덱싱 방법을 혼합해야합니다.

예를 들어 다음 DataFrame을 고려하십시오. 최선의 방법 행까지 'C'에 등을 슬라이스 처음 네 개의 열을?

>>> df = pd.DataFrame(np.nan, 
                      index=list('abcde'),
                      columns=['x','y','z', 8, 9])
>>> df
    x   y   z   8   9
a NaN NaN NaN NaN NaN
b NaN NaN NaN NaN NaN
c NaN NaN NaN NaN NaN
d NaN NaN NaN NaN NaN
e NaN NaN NaN NaN NaN

이전 버전의 팬더 (0.20.0 이전) ix에서는이 작업을 매우 깔끔하게 수행 할 수 있습니다. 레이블별로 행을 ix잘라 내고 위치별로 열을 슬라이스 할 수 있습니다 (열의 4경우 열 이름이 아니기 때문에 기본적으로 위치 기반 슬라이싱을 사용합니다) ) :

>>> df.ix[:'c', :4]
    x   y   z   8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN

이후 버전의 팬더에서는 iloc다른 방법을 사용 하여이 결과를 얻을 수 있습니다 .

>>> df.iloc[:df.index.get_loc('c') + 1, :4]
    x   y   z   8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN

get_loc()"이 색인에서 레이블의 위치를 ​​얻습니다"를 의미하는 색인 ​​방법입니다. 와의 슬라이싱 iloc은 엔드 포인트를 배제 하므로 행 'c'를 원할 경우이 값에 1을 추가해야합니다.

팬더의 문서에 더 많은 예제가 있습니다 .


12
좋은 설명! 내가 항상 가지고 있었던 관련 질문 중 하나는 loc, iloc 및 ix가 SettingWithCopy 경고와 어떤 관계입니까? 이 일부 문서는하지만, 솔직히 말해서 나는 조금 혼란 여전히 해요 pandas.pydata.org/pandas-docs/stable/...
measureallthethings을

3
@measureallthethings : loc, iloc그리고 ix그들이 서로 연결하는 경우 힘은 여전히 경고를 트리거합니다. 연결된 문서에서 예제 DataFrame을 사용하면 첫 번째 인덱싱 작업에서 뷰가 아닌 데이터 복사본이 반환 될 수 있으므로 dfmi.loc[:, 'one'].loc[:, 'second']경고가 트리거 dfmi['one']['second']됩니다.
Alex Riley

Date를 사용하여 DateIndex를 조회하려면 무엇을 사용 df.ix[date, 'Cash']합니까?
cjm2671

@ cjm2671 : 둘 loc또는 ix그 경우에 작동합니다. 예를 들어 df.loc['2016-04-29', 'Cash']'현금'열에서 특정 날짜의 모든 행 인덱스를 반환합니다. (문자열을 사용하여 인덱스를 검색 할 때 원하는대로 구체적으로 지정할 수 있습니다. 예를 들어 '2016-01'2016 년 1 월에 떨어지는 모든 날짜 시간을 선택하고, ''2016-01-02 11 '은 2016 년 1 월 2 일에 시간 11을 사용하여 날짜 시간을 선택합니다. ?? : ?? .)
Alex Riley

어떤 시점에서이 답변을 업데이트하려는 경우 여기에 ix github.com/pandas-dev/pandas/issues/14218
JohnE

142

iloc정수 위치에 따라 작동합니다. 따라서 행 레이블이 무엇이든 관계없이 항상 첫 번째 행을 가져올 수 있습니다.

df.iloc[0]

또는 마지막 다섯 행을 수행하여

df.iloc[-5:]

열에서도 사용할 수 있습니다. 세 번째 열을 검색합니다.

df.iloc[:, 2]    # the : in the first position indicates all rows

그것들을 결합하여 행과 열의 교차점을 얻을 수 있습니다.

df.iloc[:3, :3] # The upper-left 3 X 3 entries (assuming df has 3+ rows and columns)

반면에 .loc명명 된 인덱스를 사용하십시오. 문자열을 행 및 열 레이블로 사용하여 데이터 프레임을 설정합시다.

df = pd.DataFrame(index=['a', 'b', 'c'], columns=['time', 'date', 'name'])

그런 다음 첫 행을 얻을 수 있습니다.

df.loc['a']     # equivalent to df.iloc[0]

'date'열의 두 번째 두 행

df.loc['b':, 'date']   # equivalent to df.iloc[1:, 1]

등등. 이제, 그것은의 기본 행 및 열 인덱스는 지적 아마 가치가 DataFrame정수가 0이 경우에 ilocloc같은 방식으로 작동합니다. 이것이 세 가지 예가 동일한 이유입니다. 문자열 또는 날짜 시간과 같이 숫자가 아닌 인덱스 df.loc[:5] 가 있으면 오류가 발생합니다.

또한 데이터 프레임을 사용하여 열 검색을 수행 할 수 있습니다 __getitem__.

df['time']    # equivalent to df.loc[:, 'time']

이제 위치와 명명 된 인덱싱, 즉 행의 이름과 열의 위치를 ​​사용하여 인덱싱을 혼합하려고한다고 가정합니다 (명확히 말하면 행 인덱스에 문자열과 정수가있는 데이터 프레임을 만드는 대신 데이터 프레임에서 선택하는 것을 의미합니다) 열 색인). 여기가 .ix온다 :

df.ix[:2, 'time']    # the first two rows of the 'time' column

부울 벡터를 loc메소드에 전달할 수 있다고 언급 할 가치가 있다고 생각합니다 . 예를 들면 다음과 같습니다.

 b = [True, False, True]
 df.loc[b] 

의 첫 번째와 세 번째 행을 반환합니다 df. 이것은 df[b]선택 과 동일 하지만 부울 벡터를 통해 할당하는 데에도 사용할 수 있습니다.

df.loc[b, 'name'] = 'Mary', 'John'

df.iloc [:, :]가 모든 행과 열에 해당합니까?
Alvis

그렇듯이입니다 df.loc[:, :]. 전체 값을 다시 할당 DataFrame하거나보기를 만드는 데 사용할 수 있습니다 .
JoeCondron

119

내 의견으로는, 누락 된 값 만있는 DataFrame을 사용하기 때문에 허용되는 대답이 혼란 스럽습니다. 나는 또한 용어처럼하지 않는 위치에 기반 을 위해 .iloc대신, 선호하는 위치의 정수 훨씬 더 자세한 설명과 정확히 같은 .iloc의미합니다. 핵심 단어는 정수입니다- .iloc정수가 필요합니다.

자세한 내용 은 서브셋 선택에 대한 매우 자세한 블로그 시리즈 를 참조하십시오.


.ix는 더 이상 사용되지 않으며 모호하므로 절대 사용해서는 안됩니다.

때문에 .ixIS가되지 않는 우리는 차이점에 초점을 맞출 것이다 .loc.iloc.

차이점에 대해 이야기하기 전에 DataFrame에 각 열과 각 인덱스를 식별하는 데 도움이되는 레이블이 있다는 것을 이해해야합니다. 샘플 DataFrame을 살펴 보겠습니다.

df = pd.DataFrame({'age':[30, 2, 12, 4, 32, 33, 69],
                   'color':['blue', 'green', 'red', 'white', 'gray', 'black', 'red'],
                   'food':['Steak', 'Lamb', 'Mango', 'Apple', 'Cheese', 'Melon', 'Beans'],
                   'height':[165, 70, 120, 80, 180, 172, 150],
                   'score':[4.6, 8.3, 9.0, 3.3, 1.8, 9.5, 2.2],
                   'state':['NY', 'TX', 'FL', 'AL', 'AK', 'TX', 'TX']
                   },
                  index=['Jane', 'Nick', 'Aaron', 'Penelope', 'Dean', 'Christina', 'Cornelia'])

여기에 이미지 설명을 입력하십시오

굵게 표시된 모든 단어 는 레이블입니다. 라벨은, age, color, food, height, scorestate에 사용되는 . 다른 레이블, Jane, Nick, Aaron, Penelope, Dean, Christina, Cornelia에 사용되는 인덱스 .


DataFrame에서 특정 행을 선택하는 기본 방법은 .loc.iloc인덱서를 사용하는 것입니다. 이 인덱서는 각각 동시에 열을 선택하는 데 사용할 수 있지만 지금은 행에 집중하는 것이 더 쉽습니다. 또한 각 인덱서는 이름 바로 다음에 오는 일련의 대괄호를 사용하여 선택합니다.

.loc은 레이블로만 데이터를 선택합니다.

먼저 .loc인덱스 또는 열 레이블로 데이터를 선택 하는 인덱서 에 대해 이야기하겠습니다 . 샘플 DataFrame에서 인덱스의 값으로 의미있는 이름을 제공했습니다. 많은 DataFrame에는 의미있는 이름이 없으며 대신 0에서 n-1 사이의 정수로 기본 설정됩니다. 여기서 n은 DataFrame의 길이입니다.

사용할 수있는 세 가지 입력이 있습니다 .loc

  • 문자열 목록
  • 문자열을 시작 및 중지 값으로 사용하는 슬라이스 표기법

문자열이있는 .loc을 사용하여 단일 행 선택

단일 데이터 행을 선택하려면 다음에 괄호 안에 색인 레이블을 배치하십시오 .loc.

df.loc['Penelope']

이것은 데이터 행을 시리즈로 리턴합니다.

age           4
color     white
food      Apple
height       80
score       3.3
state        AL
Name: Penelope, dtype: object

문자열 목록이있는 .loc을 사용하여 여러 행 선택

df.loc[['Cornelia', 'Jane', 'Dean']]

목록에 지정된 순서대로 행이있는 DataFrame을 반환합니다.

여기에 이미지 설명을 입력하십시오

슬라이스 표기법이있는 .loc를 사용하여 여러 행 선택

슬라이스 표기법은 시작, 중지 및 단계 값으로 정의됩니다. 레이블로 슬라이스 할 때 팬더는 리턴 값에 중지 값을 포함합니다. Aaron에서 Dean까지 다음 조각이 포함됩니다. 단계 크기는 명시 적으로 정의되어 있지 않지만 기본값은 1입니다.

df.loc['Aaron':'Dean']

여기에 이미지 설명을 입력하십시오

복잡한 슬라이스는 Python 목록과 같은 방식으로 가져올 수 있습니다.

.iloc은 정수 위치로만 데이터를 선택합니다

이제로 넘어 갑시다 .iloc. DataFrame의 모든 데이터 행과 열에는이를 정의하는 정수 위치가 있습니다. 이것은 출력에 시각적으로 표시되는 레이블에 추가됩니다 . 정수 위치는 단순히 0에서 시작하는 상단 / 왼쪽의 행 / 열 수입니다.

사용할 수있는 세 가지 입력이 있습니다 .iloc

  • 정수
  • 정수 목록
  • 시작 및 중지 값으로 정수를 사용하는 슬라이스 표기법

정수가있는 .iloc을 사용하여 단일 행 선택

df.iloc[4]

5 번째 행 (정수 위치 4)을 Series로 반환합니다.

age           32
color       gray
food      Cheese
height       180
score        1.8
state         AK
Name: Dean, dtype: object

정수 목록이있는 .iloc을 사용하여 여러 행 선택

df.iloc[[2, -2]]

세 번째와 두 번째 행부터 마지막 ​​행까지의 DataFrame을 반환합니다.

여기에 이미지 설명을 입력하십시오

슬라이스 표기법이있는 .iloc을 사용하여 여러 행 선택

df.iloc[:5:3]

여기에 이미지 설명을 입력하십시오


.loc 및 .iloc을 사용하여 행과 열을 동시에 선택

두 가지의 뛰어난 기능 중 하나 .loc/.iloc는 행과 열을 동시에 선택할 수 있다는 것입니다. 위의 예에서 모든 열은 각 선택 항목에서 반환되었습니다. 행과 동일한 입력 유형을 가진 열을 선택할 수 있습니다. 행과 열 선택을 쉼표로 구분하면 됩니다.

예를 들어 다음과 같이 열 높이, 점수 및 상태만으로 Jane과 Dean 열을 선택할 수 있습니다.

df.loc[['Jane', 'Dean'], 'height':]

여기에 이미지 설명을 입력하십시오

행의 레이블 목록과 열의 슬라이스 표기법을 사용합니다.

.iloc정수만 사용하여 자연스럽게 유사한 작업을 수행 할 수 있습니다 .

df.iloc[[1,4], 2]
Nick      Lamb
Dean    Cheese
Name: food, dtype: object

라벨과 정수 위치를 통한 동시 선택

.ix유용하지만 때로는 혼란스럽고 모호한 레이블 및 정수 위치와 동시에 선택하는 데 사용되었으며 고맙게도 더 이상 사용되지 않습니다. 레이블과 정수 위치를 혼합하여 선택해야하는 경우 선택 레이블 또는 정수 위치를 모두 선택해야합니다.

우리가 행을 선택하려는 경우 예를 들어, NickCornelia열 2, 4와 함께를, 우리가 사용할 수있는 .loc다음과 라벨에 정수를 변환 :

col_names = df.columns[[2, 4]]
df.loc[['Nick', 'Cornelia'], col_names] 

또는 get_locindex 메소드 를 사용하여 인덱스 레이블을 정수로 변환하십시오 .

labels = ['Nick', 'Cornelia']
index_ints = [df.index.get_loc(label) for label in labels]
df.iloc[index_ints, [2, 4]]

부울 선택

.loc 인덱서는 부울 선택을 수행 할 수도 있습니다. 우리가 모든 행을 찾는 데 관심이 있다면 예를 들어, 연령은 30 위에 반환 단지 wher foodscore열이 우리가 다음을 수행 할 수 있습니다 :

df.loc[df['age'] > 30, ['food', 'score']] 

이것을 복제 .iloc할 수 는 있지만 부울 시리즈를 전달할 수는 없습니다. 부울 시리즈를 다음과 같이 numpy 배열로 변환해야합니다.

df.iloc[(df['age'] > 30).values, [2, 4]] 

모든 행 선택

.loc/.iloc열 선택에만 사용할 수 있습니다 . 다음과 같이 콜론을 사용하여 모든 행을 선택할 수 있습니다.

df.loc[:, 'color':'score':2]

여기에 이미지 설명을 입력하십시오


인덱싱 연산자 인 []은 행과 열을 동시에 선택할 수는 없습니다.

대부분의 사람들은 열을 선택하는 DataFrame 인덱싱 연산자의 기본 목적에 익숙합니다. 문자열은 단일 열을 Series로 선택하고 문자열 목록은 여러 열을 DataFrame으로 선택합니다.

df['food']

Jane          Steak
Nick           Lamb
Aaron         Mango
Penelope      Apple
Dean         Cheese
Christina     Melon
Cornelia      Beans
Name: food, dtype: object

목록을 사용하여 여러 열을 선택합니다

df[['food', 'score']]

여기에 이미지 설명을 입력하십시오

사람들이 익숙하지 않은 것은 슬라이스 표기법을 사용할 때 행 레이블 또는 정수 위치로 선택이 발생한다는 것입니다. 이것은 매우 혼란스럽고 거의 사용하지 않는 것이지만 작동합니다.

df['Penelope':'Christina'] # slice rows by label

여기에 이미지 설명을 입력하십시오

df[2:6:2] # slice rows by integer location

여기에 이미지 설명을 입력하십시오

명확성의 .loc/.iloc선택 행에 대해 매우 바람직하다. 인덱싱 연산자만으로는 행과 열을 동시에 선택할 수 없습니다.

df[3:5, 'color']
TypeError: unhashable type: 'slice'

6
와우, 이것은 프로그래밍 주제와 관련하여 아주 잘 설명되고 자명 한 설명 중 하나였습니다. 행이나 열에서 작동하는 일반 색인에 대해 마지막에 설명 한 것은 우리가 loc과 iloc을 가진 이유 중 하나입니다 방법. 나는 데이터 캠프 코스에서 그 경고에 부딪쳤다. a.) df.columns와 df.index는 무엇을 반환합니까? 문자열 목록입니까? 목록 인 경우 목록에서이 df.columns [[2,4]]와 같은 두 가지 요소에 액세스 할 수 있습니까? b.) df.columns에서 get_loc ()을 호출 할 수 있습니까? c.) iloc의 경우 왜 df [ 'age']> 30.values를 호출해야합니까?
pragun

내가 본 것 중 최고의 해답 자.
최대

이것은 정말 좋은 대답입니다 .ix에 많이 들어 가지 않아서 더 이상 사용되지 않으며 딥 다이빙에 무의미합니다. 감사.
omabena
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.