Hierarchical Indexing
계층적 인덱싱이란,
a라는 인덱스 안에 1, 2, 3이라는 인덱스가 있고,
c라는 인덱스 안에 또 1, 2, 3가 있는 그런 형태입니다.
예를 들어 홍길동이라는 이름이 있다고 가정해봅시다.
물론 남자 같은 이름이지만 여자가 있을 수도 있습니다.
남자 인덱스 안에 [홍길동, 24] 이런 식으로 넣고, 여자 인덱스 안에 [홍길동, 23] 이런 식으로 넣을 수 있습니다.
이때 사용하는 것이 Hierarchical Indexing 입니다.
data = pd.Series(np.random.randn(9),
index=[['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'],
[1, 2, 3, 1, 3, 1, 2, 2, 3]])
data
a 1 -0.204708
2 0.478943
3 -0.519439
b 1 -0.555730
3 1.965781
c 1 1.393406
2 0.092908
d 2 0.281746
3 0.769023
dtype: float64
이해가 되시나요?
이때 index를 추출하면,
data.index
MultiIndex([('a', 1),
('a', 2),
('a', 3),
('b', 1),
('b', 3),
('c', 1),
('c', 2),
('d', 2),
('d', 3)],
)
이렇게 나옵니다.
최상단 Index(level = 0)를 기준으로 loc 등의 함수를 사용할 수 있습니다.
이때 level 1에서 인덱스가 2인 row를 추출하고 싶다면,
data.loc[:, 2]
a 0.478943
c 0.092908
d 0.281746
dtype: float64
이렇게 사용하면 간단하게 추출할 수 있습니다.
위의 데이터는 Series Data이지만, 이를 unstack() 함수를 이용하여 DataFrame 형태로 변환할 수 있습니다.
data.unstack()
1 2 3
a -0.204708 0.478943 -0.519439
b -0.555730 NaN 1.965781
c 1.393406 0.092908 NaN
d NaN 0.281746 0.769023
이를 또 다시 stack() 함수를 이용하여 Series 형태로 변환할 수 있습니다.
data.unstack().stack()
a 1 -0.204708
2 0.478943
3 -0.519439
b 1 -0.555730
3 1.965781
c 1 1.393406
2 0.092908
d 2 0.281746
3 0.769023
dtype: float64
만약 DataFrame 형태로 사용하고, Column에도 계층적 인덱싱을 적용하고 싶다면, 아래와 같이 하면 됩니다.
frame = pd.DataFrame(np.arange(12).reshape((4, 3)),
index=[['a', 'a', 'b', 'b'], [1, 2, 1, 2]],
columns=[['Ohio', 'Ohio', 'Colorado'],
['Green', 'Red', 'Green']])
frame
Ohio Colorado
Green Red Green
a 1 0 1 2
2 3 4 5
b 1 6 7 8
2 9 10 11
이때도 name을 설정할 수 있는데, 이때는 리스트 형태로 각각 넣어줘야 합니다.
frame.index.names = ['key1', 'key2']
frame.columns.names = ['state', 'color']
frame
state Ohio Colorado
color Green Red Green
key1 key2
a 1 0 1 2
2 3 4 5
b 1 6 7 8
2 9 10 11
이때 Ohio 주만 추출하면,
frame['Ohio']
color Green Red
key1 key2
a 1 0 1
2 3 4
b 1 6 7
2 9 10
이렇게 깔끔하게 Ohio 주만 추출합니다.
만약에 key1과 key2의 레벨을 바꾸고 싶다면, swaplevel() 함수를 이용하면 됩니다.
frame.swaplevel('key1', 'key2')
state Ohio Colorado
color Green Red Green
key2 key1
1 a 0 1 2
2 a 3 4 5
1 b 6 7 8
2 b 9 10 11
기존의 frame에서 레벨 1을 기준으로 정렬하면 어떻게 될까요?
frame.sort_index(level=1)
state Ohio Colorado
color Green Red Green
key1 key2
a 1 0 1 2
b 1 6 7 8
a 2 3 4 5
b 2 9 10 11
이렇게 key2를 기준으로 정렬하게 됩니다.
혹은 기존의 frame에서 level 0과 level 1의 위치를 바꾼 후, level 0에 대해 정렬하면 어떻게 될까요?
frame.swaplevel(0, 1).sort_index(level=0)
state Ohio Colorado
color Green Red Green
key2 key1
1 a 0 1 2
b 6 7 8
2 a 3 4 5
b 9 10 11
참고로 기존의 frame은 아래와 같습니다.
state Ohio Colorado
color Green Red Green
key1 key2
a 1 0 1 2
2 3 4 5
b 1 6 7 8
2 9 10 11
참고로 key2를 기준으로 sum 함수를 적용할 수도 있습니다.
frame.sum(level='key2')
state Ohio Colorado
color Green Red Green
key2
1 6 8 10
2 12 14 16
key2가 1인 row와 key2가 2인 row끼리 더합니다.
다른 방식으로 color를 기준으로 더할 수도 있습니다.
frame.sum(level='color', axis=1)
color Green Red
key1 key2
a 1 2 1
2 8 4
b 1 14 7
2 20 10
참고로 axis = 0으로 하면 오류가 발생합니다.