Pandas DataFrame 인덱싱

@winuss · October 01, 2020 · 7 min read

DataFrame 인덱싱

DataFrame에서 특정한 데이터만 골라내는 것을 인덱싱(indexing)이라고 한다. Pandas는 numpy행렬과 같이 쉼표를 사용한 (행 인덱스, 열 인덱스) 형식의 2차원 인덱싱을 지원하기 위해 다음과 같은 특별한 인덱서(indexer) 속성을 제공한다.

  • loc : 라벨값 기반의 2차원 인덱싱
  • iloc : 순서를 나타내는 정수 기반의 2차원 인덱싱
  • at : 라벨값 기반의 2차원 인덱싱 (한개의 스카라 값만 찾는다.)
  • iat : 순서를 나타내는 정수 기반의 2차원 인덱싱 (한개의 스칼라 값만 찾는다.)

loc 인덱서

df.loc[행 인덱서값]

또는

df.loc[행 인덱서값, 열 인덱서값]

이때 인덱싱 값은 다음중 하나이다. 행 인덱싱값은 정수 또는 행 인덱스데이터 이고 열 인덱싱값은 라벨 문자열 이다.

  • 인덱스데이터
  • 인덱스데이터 슬라이스
  • 인덱스데이터 리스트
  • 같은 행 인덱스를 가지는 Boolean 시리즈 (행 인덱싱의 경우)
  • 위의 값들을 반환하는 함수

글로 정의를 하자니 확 와닿지가 않는다.

데이터 프레임을 예로 들어 살펴보자.

import pandas as pd
import numpy as np
df = pd.DataFrame(np.arange(10, 22).reshape(3, 4),
                  index=["a", "b", "c"],
                  columns=["A", "B", "C", "D"])
df
A B C D
a 10 11 12 13
b 14 15 16 17
c 18 19 20 21

인덱싱값을 하나만 받는 경우

만약 loc 인덱서를 사용하면서 인덱스를 하나만 넣으면 행을 선택한다.

인덱스데이터가 "a"인 행을 고르면 행이 Series로 출력된다. Series로 항하로 길게 출력되긴하지만 데이터를 보면 행의 데이터를 가져오고 있다.

df.loc["a"]
A    10
B    11
C    12
D    13
Name: a, dtype: int32

인덱스데이터 슬라이스

df.loc["b":"c"]
A B C D
b 14 15 16 17
c 18 19 20 21
df["b":"c"] # loc를 쓰지 않는 경우
A B C D
b 14 15 16 17
c 18 19 20 21

인덱스데이터의 리스트도 가능하다.

df.loc[["b","c"]] # df[["b", "c"]]  # KeyError
A B C D
b 14 15 16 17
c 18 19 20 21

인덱스를 가지는 Boolean Series도 행을 선택하는 인덱싱 값으로 쓸 수 있다.

df.A > 15
a    False
b    False
c     True
Name: A, dtype: bool
df.loc[df.A > 15] # df.A > 15 = True인 행만 가져옴
A B C D
c 18 19 20 21

함수를 사용할 수도 있다.

def select_rows(df):
    return df.A > 15
select_rows(df)
a    False
b    False
c     True
Name: A, dtype: bool
df.loc[select_rows(df)]
A B C D
c 18 19 20 21

loc 인덱서가 없는 경우에 사용했던 라벨 인덱싱이나 라벨 리스트 인덱싱은 불가능하다.

df.loc["A"]  # KeyError
df.loc[["A", "B"]]  # KeyError

원래 행 인덱스값이 정수인 경우에는 슬라이싱도 라벨 슬라이싱 방식을 따른다.

df2 = pd.DataFrame(np.arange(10, 26).reshape(4, 4), columns=["A", "B", "C", "D"])
df2
A B C D
0 10 11 12 13
1 14 15 16 17
2 18 19 20 21
3 22 23 24 25
df2.loc[1:2]
A B C D
1 14 15 16 17
2 18 19 20 21

위 내용을 표로 정리하면,

인덱싱 값 가능 결과 자료형 추가사항
행 인덱스값(정수) O 시리즈
행 인덱스값(정수) 슬라이스 O 데이터프레임 loc가 없는 경우와 같음
행 인덱스값(정수) 리스트 O 데이터프레임
Boolean Series O 데이터프레임 시리즈의 인덱스가 데이터프레임의 행 인덱스와 같아야 한다.
Boolean Series 반환 함수 O 데이터프레임
열 라벨 X loc가 없는 경우에만 쓸 수 있다.
열 라벨 리스트 X loc가 없는 경우에만 쓸 수 있다.

인덱싱값을 행과 열 모두 받는 경우

인덱싱값을 행과 열 모두 받으려면 df.loc[행 인덱스, 열 인덱스]와 같은 형태로 사용한다. 행 인덱스 라벨값이 a, 열 인덱스 라벨값이 A인 위치의 값을 구해보자.

df.loc['a', 'A']
10

인덱싱값으로 라벨 데이터의 슬라이싱 또는 리스트를 사용할 수도 있다.

df.loc["b":, "A"]
b    14
c    18
Name: A, dtype: int32
df.loc["a", :]
A    10
B    11
C    12
D    13
Name: a, dtype: int32
df.loc[["a","b"], ["B","D"]]
B D
a 11 13
b 15 17

행 인덱스가 같은 Boolean Series 이러한 Boolean Series 반환하는 함수도 행의 인덱싱 값이 될 수 있다.

df.loc[df.A > 10, ["C", "D"]]
C D
b 16 17
c 20 21

iloc 인덱서

iloc인덱서는 loc인덱서와 반대로 라벨이 아니라 순서를 나타내는 정수 인덱스만 받는다. 다른 사항은 loc인덱서와 같다.

df.iloc[0, 1]
11
df.iloc[:2,2]
a    12
b    16
Name: C, dtype: int32

loc인덱서와 마찬가지로 인덱스가 하나만 들어가면 행을 선택한다.

df.iloc[-1]
A    18
B    19
C    20
D    21
Name: c, dtype: int32
df.iloc[-1] = df.iloc[-1] * 2
df
A B C D
a 10 11 12 13
b 14 15 16 17
c 72 76 80 84

at, iat 인덱서

at, iat 인덱서는 loc, 'iloc` 인덱서와 비슷하지만 하나의 스칼라 값을 뽑을 때만 사용한다. 하여 빠른 인덱싱 속도가 요구되는 경우에 사용한다.

%timeit df.loc["a", "A"]
5.62 µs ± 87.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit df.at["a", "A"]
3.11 µs ± 29.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit df.iloc[0, 0]
16.8 µs ± 462 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit df.iat[0, 0]
14.8 µs ± 262 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

출처 : 데이터사이언스 스쿨(datascienceschool.net)

@winuss
Hello :) Developer notes!