Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python Pandas에서 인덱스 레이블로 데이터 하위 집합을 선택하는 방법

소개

Pandas는 인덱스 위치(index position) 또는 인덱스 레이블(index label) 두 가지 방식으로 데이터의 하위 집합을 선택할 수 있는 이중 선택 기능을 제공합니다. 이번 글에서는 인덱스 레이블을 활용해 "데이터의 하위 집합을 선택하는 방법"을 자세히 살펴보겠습니다.

먼저 짚고 넘어갈 점은, 파이썬의 딕셔너리(dictionary)와 리스트(list)라는 내장 데이터 구조 역시 각각 인덱스 레이블과 인덱스 위치를 통해 데이터에 접근한다는 사실입니다. 딕셔너리의 키는 문자열, 정수 또는 튜플이어야 하며, 리스트는 정수(위치)나 슬라이스 객체를 사용해서만 요소를 선택할 수 있습니다.

Pandas에는 .loc.iloc이라는 두 가지 속성이 마련되어 있으며, 각각 고유한 방식으로 인덱싱 작업을 수행합니다. .iloc은 오직 위치 기반으로만 데이터를 선택하며 파이썬 리스트와 비슷하게 동작합니다. 반면 .loc은 인덱스 레이블 기반으로만 선택하며, 파이썬 딕셔너리의 동작 방식과 유사합니다.

.loc[]로 인덱스 레이블 기반 데이터 선택하기

lociloc 속성은 Series와 DataFrame 모두에서 사용할 수 있습니다.

1. 영화 제목을 인덱스로 지정하여 데이터셋 불러오기

import pandas as pd
movies = pd.read_csv("https://raw.githubusercontent.com/sasankac/TestDataSet/master/movies_data.csv",
index_col="title",
usecols=["title","budget","vote_average","vote_count"])

인덱스를 미리 정렬해 두는 것을 항상 권장합니다. 특히 인덱스가 문자열로 구성된 경우 더욱 그렇습니다. 대용량 데이터셋을 다룰 때 인덱스가 정렬되어 있으면 성능 차이를 실감하게 됩니다.

movies.sort_index(inplace = True)
movies.head(3)
     budget vote_average vote_count
title
___________________________________
#Horror 1500000 3.3 52
(500) Days of Summer 7500000 7.2 2904
10 Cloverfield Lane 15000000 6.8 2468

sort_index 메서드에 inplace=True 매개변수를 지정해 인덱스를 정렬했습니다.

2. .loc 문법의 흥미로운 특징

loc 메서드 문법에서 흥미로운 점은 소괄호()가 아닌 대괄호[]를 사용한다는 것입니다. 아마도 일관성을 위해서인 것으로 보입니다. 즉, Series에 []를 적용하면 행을 추출하고, DataFrame에 적용하면 열을 가져오게 됩니다.

# "Spider-Man 3" 추출 (저는 스파이더맨의 큰 팬은 아닙니다)
movies.loc["Spider-Man 3"]
budget 258000000.0
vote_average 5.9
vote_count 3576.0
Name: Spider-Man 3, dtype: float64

3. 슬라이스로 여러 값 추출하기

슬라이스를 사용하면 여러 값을 한 번에 가져올 수 있습니다. 문자열 레이블 기반이므로 검색 조건에 해당하는 모든 데이터가 끝값인 "Avatar"까지 포함되어 반환됩니다.

기억하세요 - 파이썬 리스트에서는 슬라이싱 시 마지막 값이 제외되지만, 문자열 레이블로 작업할 경우 끝값도 포함됩니다(inclusive).

movies.loc["Alien":"Avatar"]
budget vote_average vote_count
title
Alien 11000000 7.9 4470
Alien Zone 0 4.0 3
Alien: Resurrection 70000000 5.9 1365
Aliens 18500000 7.7 3220
Aliens in the Attic 45000000 5.3 244
... ... ... ...
Australia 130000000 6.3 694
Auto Focus 7000000 6.1 56
Automata 7000000 5.6 670
Autumn in New York 65000000 5.7 135
Avatar 237000000 7.2 11800

167 rows × 3 columns

4. 서로 인접하지 않은 여러 영화 선택하기

서로 붙어 있지 않은 임의의 두 개 이상의 영화를 가져올 수 있을까요? 물론 가능합니다. 다만 원하는 영화 목록을 리스트로 전달해야 하므로 약간의 추가 작업이 필요합니다. 즉, 대괄호 안에 또 다른 대괄호를 중첩해 사용해야 합니다.

movies.loc[["Avatar","Avengers: Age of Ultron"]]
budget vote_average vote_count
title
Avatar 237000000 7.2 11800
Avengers: Age of Ultron 280000000 7.3 6767

5. 선택 순서 변경하기

선택 순서를 바꾸고 싶다면 원하는 레이블 목록을 순서대로 지정하면 됩니다.

레이블 목록을 지정해 데이터를 추출하는 방식은 편리하지만, 만약 값을 잘못 입력하면 어떻게 될까요? 과거에는 잘못 입력된 레이블에 대해 누락 값(NaN)이 채워졌습니다. 하지만 최신 버전에서는 더 이상 그렇지 않고, 존재하지 않는 레이블이 포함되면 예외(exception)를 발생시킵니다.

movies.loc[["Avengers: Age of Ultron","Avatar","When is Avengers next movie?"]]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
----> 1 movies.loc[["Avengers: Age of Ultron","Avatar","When is Avengers next movie?"]]
...
-> 1654 raise KeyError(
1655 "Passing list-likes to .loc or [] with any missing labels "
1656 "is no longer supported, see "

KeyError: 'Passing list-likes to .loc or [] with any missing labels is no longer supported'

이런 상황을 피하는 한 가지 방법은 해당 값이 인덱스에 존재하는지 직접 확인하는 것입니다.

"When is Avengers next movie?" in movies.index

출력 결과

False

오류를 무시하고 계속 진행하고 싶다면 아래와 같이 query 메서드를 활용할 수 있습니다.

movies.query("title in ('Avatar','When is Avengers next Movie?')")
budget vote_average vote_count
title
Avatar 237000000 7.2 11800