[Python] 데이터 사이언스 스쿨 - 4.5 데이터프레임 인덱스 조작
Updated:
데이터 사이언스 스쿨 자료를 토대로 공부한 내용입니다.
실습과정에서 필요에 따라 내용의 누락 및 추가, 수정사항이 있습니다.
4.5 데이터프레임 인덱스 조작
데이터프레임 인덱스 설정 및 제거
import numpy as np
import pandas as pd
# 데이터 프레임 생성
np.random.seed(0)
df1 = pd.DataFrame(np.vstack([list('ABCDE'),
np.round(np.random.rand(3, 5), 2)]).T,
columns=["C1", "C2", "C3", "C4"])
df1
C1 | C2 | C3 | C4 | |
---|---|---|---|---|
0 | A | 0.55 | 0.65 | 0.79 |
1 | B | 0.72 | 0.44 | 0.53 |
2 | C | 0.6 | 0.89 | 0.57 |
3 | D | 0.54 | 0.96 | 0.93 |
4 | E | 0.42 | 0.38 | 0.07 |
# set_index: 기존 열을 인덱스로 사용
df2 = df1.set_index("C1")
df2
C2 | C3 | C4 | |
---|---|---|---|
C1 | |||
A | 0.55 | 0.65 | 0.79 |
B | 0.72 | 0.44 | 0.53 |
C | 0.6 | 0.89 | 0.57 |
D | 0.54 | 0.96 | 0.93 |
E | 0.42 | 0.38 | 0.07 |
set_index()
를 이용하면 기존의 열을 행 인덱스로 사용 가능하다.
# 새로 인덱스 지정시 기존 인덱스는 사라짐
df2.set_index("C2")
C3 | C4 | |
---|---|---|
C2 | ||
0.55 | 0.65 | 0.79 |
0.72 | 0.44 | 0.53 |
0.6 | 0.89 | 0.57 |
0.54 | 0.96 | 0.93 |
0.42 | 0.38 | 0.07 |
set_index()
로 인덱스를 지정하면 기존 인덱스는 사라진다.
# reset_index: 인덱스를 보통의 자료열로 복구 - 인덱스는 정수 인덱스로 바뀜
df2.reset_index()
C1 | C2 | C3 | C4 | |
---|---|---|---|---|
0 | A | 0.55 | 0.65 | 0.79 |
1 | B | 0.72 | 0.44 | 0.53 |
2 | C | 0.6 | 0.89 | 0.57 |
3 | D | 0.54 | 0.96 | 0.93 |
4 | E | 0.42 | 0.38 | 0.07 |
reset_index()
를 사용하면 인덱스를 열로 사용한다.
# drop 옵션을 주면 자료가 복구되지 않고 버려짐
df2.reset_index(drop=True)
C2 | C3 | C4 | |
---|---|---|---|
0 | 0.55 | 0.65 | 0.79 |
1 | 0.72 | 0.44 | 0.53 |
2 | 0.6 | 0.89 | 0.57 |
3 | 0.54 | 0.96 | 0.93 |
4 | 0.42 | 0.38 | 0.07 |
- drop 옵션을 True로 설정하면 인덱스를 열로 사용하지 않고 제거한다.
연습 문제 4.5.1
5명의 학생의 국어, 영어, 수학 점수를 나타내는 데이터프레임을 다음과 같이 만든다.
-
학생 이름을 나타내는 열을 포함시키지 않고 데이터프레임
df_score1
을 생성한 후,df_score1.index
속성에 학생 이름을 나타내는 열을 지정하여 인덱스를 지정한다.reset_index
명령으로 이 인덱스 열을 명령으로 일반 데이터열로 바꾸여 데이터프레임df_score2
을 만든다. -
학생 이름을 나타내는 열이 일반 데이터 열을 포함하는 데이터프레임
df_score2
에set_index
명령을 적용하여 다시 학생 이름을 나타내는 열을 인덱스로 변경한다.
# 데이터 프레임 생성
np.random.seed(93)
df_score1 = pd.DataFrame(
np.random.randint(0,101, size=(5,3)),
columns = ["국어", "수학", "영어"]
)
df_score1
국어 | 수학 | 영어 | |
---|---|---|---|
0 | 37 | 91 | 4 |
1 | 24 | 79 | 97 |
2 | 85 | 48 | 77 |
3 | 52 | 52 | 51 |
4 | 21 | 49 | 74 |
# 인덱스 지정하기
df_score1.index = ["학생1", "학생2", "학생3", "학생4", "학생5"]
df_score1.index.name = "학생"
df_score1
국어 | 수학 | 영어 | |
---|---|---|---|
학생 | |||
학생1 | 37 | 91 | 4 |
학생2 | 24 | 79 | 97 |
학생3 | 85 | 48 | 77 |
학생4 | 52 | 52 | 51 |
학생5 | 21 | 49 | 74 |
# 1. reset_index
df_score2 = df_score1.reset_index()
df_score2
학생 | 국어 | 수학 | 영어 | |
---|---|---|---|---|
0 | 학생1 | 37 | 91 | 4 |
1 | 학생2 | 24 | 79 | 97 |
2 | 학생3 | 85 | 48 | 77 |
3 | 학생4 | 52 | 52 | 51 |
4 | 학생5 | 21 | 49 | 74 |
# 2. set_index
df_score2.set_index("학생")
국어 | 수학 | 영어 | |
---|---|---|---|
학생 | |||
학생1 | 37 | 91 | 4 |
학생2 | 24 | 79 | 97 |
학생3 | 85 | 48 | 77 |
학생4 | 52 | 52 | 51 |
학생5 | 21 | 49 | 74 |
다중 인덱스
# 다중 열 인덱스
np.random.seed(0)
df3 = pd.DataFrame(np.round(np.random.randn(5, 4), 2),
columns=[["A", "A", "B", "B"],
["C1", "C2", "C1", "C2"]])
df3
A | B | |||
---|---|---|---|---|
C1 | C2 | C1 | C2 | |
0 | 1.76 | 0.40 | 0.98 | 2.24 |
1 | 1.87 | -0.98 | 0.95 | -0.15 |
2 | -0.10 | 0.41 | 0.14 | 1.45 |
3 | 0.76 | 0.12 | 0.44 | 0.33 |
4 | 1.49 | -0.21 | 0.31 | -0.85 |
-
데이터 프레임을 생성할 때 위 예시와 같이 다중 열 인덱스를 생성 가능하다.
-
columns 옵션에 상위 인덱스부터 순서대로 작성한다.
# 열 인덱스 이름 지정
df3.columns.names = ["Cidx1", "Cidx2"]
df3
Cidx1 | A | B | ||
---|---|---|---|---|
Cidx2 | C1 | C2 | C1 | C2 |
0 | 1.76 | 0.40 | 0.98 | 2.24 |
1 | 1.87 | -0.98 | 0.95 | -0.15 |
2 | -0.10 | 0.41 | 0.14 | 1.45 |
3 | 0.76 | 0.12 | 0.44 | 0.33 |
4 | 1.49 | -0.21 | 0.31 | -0.85 |
-
다중 열 인덱스도 인덱스의 이름을 각각 지정 가능하다.
-
마찬가지로 상위 인덱스 이름부터 순서대로 작성한다.
# 다중 행/열 인덱스
np.random.seed(0)
df4 = pd.DataFrame(np.round(np.random.randn(6, 4), 2),
columns=[["A", "A", "B", "B"],
["C", "D", "C", "D"]],
index=[["M", "M", "M", "F", "F", "F"],
["id_" + str(i + 1) for i in range(3)] * 2])
df4.columns.names = ["Cidx1", "Cidx2"]
df4.index.names = ["Ridx1", "Ridx2"]
df4
Cidx1 | A | B | |||
---|---|---|---|---|---|
Cidx2 | C | D | C | D | |
Ridx1 | Ridx2 | ||||
M | id_1 | 1.76 | 0.40 | 0.98 | 2.24 |
id_2 | 1.87 | -0.98 | 0.95 | -0.15 | |
id_3 | -0.10 | 0.41 | 0.14 | 1.45 | |
F | id_1 | 0.76 | 0.12 | 0.44 | 0.33 |
id_2 | 1.49 | -0.21 | 0.31 | -0.85 | |
id_3 | -2.55 | 0.65 | 0.86 | -0.74 |
- 행 인덱스도 같은 방법으로 다중 인덱스로 생성 가능하다.
행 인덱스와 열 인덱스 교환
# stack(열 인덱스 이름): 열 인덱스 -> 행 인덱스
df4.stack("Cidx1")
Cidx2 | C | D | ||
---|---|---|---|---|
Ridx1 | Ridx2 | Cidx1 | ||
M | id_1 | A | 1.76 | 0.40 |
B | 0.98 | 2.24 | ||
id_2 | A | 1.87 | -0.98 | |
B | 0.95 | -0.15 | ||
id_3 | A | -0.10 | 0.41 | |
B | 0.14 | 1.45 | ||
F | id_1 | A | 0.76 | 0.12 |
B | 0.44 | 0.33 | ||
id_2 | A | 1.49 | -0.21 | |
B | 0.31 | -0.85 | ||
id_3 | A | -2.55 | 0.65 | |
B | 0.86 | -0.74 |
-
stack()
을 사용해서 기존 열 인덱스의 이름을 지정하면 행 인덱스로 변경된다. -
staack이라는 이름처럼 데이터가 세로로 쌓이게 된다.
df4.stack(1)
Cidx1 | A | B | ||
---|---|---|---|---|
Ridx1 | Ridx2 | Cidx2 | ||
M | id_1 | C | 1.76 | 0.98 |
D | 0.40 | 2.24 | ||
id_2 | C | 1.87 | 0.95 | |
D | -0.98 | -0.15 | ||
id_3 | C | -0.10 | 0.14 | |
D | 0.41 | 1.45 | ||
F | id_1 | C | 0.76 | 0.44 |
D | 0.12 | 0.33 | ||
id_2 | C | 1.49 | 0.31 | |
D | -0.21 | -0.85 | ||
id_3 | C | -2.55 | 0.86 | |
D | 0.65 | -0.74 |
- 위 예시와 같이 열 인덱스 이름이 아닌 열 인덱스 이름의 순서를 지정해도 같은 결과가 출력된다.
# unstack(행 인덱스 이름): 행 인덱스 -> 열 인덱스
df4.unstack("Ridx2")
Cidx1 | A | B | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Cidx2 | C | D | C | D | ||||||||
Ridx2 | id_1 | id_2 | id_3 | id_1 | id_2 | id_3 | id_1 | id_2 | id_3 | id_1 | id_2 | id_3 |
Ridx1 | ||||||||||||
F | 0.76 | 1.49 | -2.55 | 0.12 | -0.21 | 0.65 | 0.44 | 0.31 | 0.86 | 0.33 | -0.85 | -0.74 |
M | 1.76 | 1.87 | -0.10 | 0.40 | -0.98 | 0.41 | 0.98 | 0.95 | 0.14 | 2.24 | -0.15 | 1.45 |
unstack()
을 사용하여 기존 행 인덱스의 이름을 지정하면 열 인덱스로 변경된다.
df4.unstack(0)
Cidx1 | A | B | ||||||
---|---|---|---|---|---|---|---|---|
Cidx2 | C | D | C | D | ||||
Ridx1 | F | M | F | M | F | M | F | M |
Ridx2 | ||||||||
id_1 | 0.76 | 1.76 | 0.12 | 0.40 | 0.44 | 0.98 | 0.33 | 2.24 |
id_2 | 1.49 | 1.87 | -0.21 | -0.98 | 0.31 | 0.95 | -0.85 | -0.15 |
id_3 | -2.55 | -0.10 | 0.65 | 0.41 | 0.86 | 0.14 | -0.74 | 1.45 |
stack()
과 마찬가지로 정수를 지정해도 같은 결과가 출력된다.
다중 인덱스가 있는 경우의 인덱싱
df4
Cidx1 | A | B | |||
---|---|---|---|---|---|
Cidx2 | C | D | C | D | |
Ridx1 | Ridx2 | ||||
M | id_1 | 1.76 | 0.40 | 0.98 | 2.24 |
id_2 | 1.87 | -0.98 | 0.95 | -0.15 | |
id_3 | -0.10 | 0.41 | 0.14 | 1.45 | |
F | id_1 | 0.76 | 0.12 | 0.44 | 0.33 |
id_2 | 1.49 | -0.21 | 0.31 | -0.85 | |
id_3 | -2.55 | 0.65 | 0.86 | -0.74 |
df4[ ("A", "C") ]
Ridx1 Ridx2
M id_1 1.76
id_2 1.87
id_3 -0.10
F id_1 0.76
id_2 1.49
id_3 -2.55
Name: (A, C), dtype: float64
- 다중 인덱스가 존재한다면 인덱싱할 때 튜플 형식으로 지정해야한다.
df4.loc[ ("M","id_1"), :]
Cidx1 Cidx2
A C 1.76
D 0.40
B C 0.98
D 2.24
Name: (M, id_1), dtype: float64
- loc 인덱서도 마찬가지로 튜플 형식으로 지정해야한다.
df4.loc[ ("M","id_1"), ("A", "C")] = 100
df4
Cidx1 | A | B | |||
---|---|---|---|---|---|
Cidx2 | C | D | C | D | |
Ridx1 | Ridx2 | ||||
M | id_1 | 100.00 | 0.40 | 0.98 | 2.24 |
id_2 | 1.87 | -0.98 | 0.95 | -0.15 | |
id_3 | -0.10 | 0.41 | 0.14 | 1.45 | |
F | id_1 | 0.76 | 0.12 | 0.44 | 0.33 |
id_2 | 1.49 | -0.21 | 0.31 | -0.85 | |
id_3 | -2.55 | 0.65 | 0.86 | -0.74 |
- 다중 인덱스에서 데이터 갱신도 튜플 형식으로 지정하면 문제없이 잘 수행된다.
df4.iloc[0:, 0:2]
Cidx1 | A | ||
---|---|---|---|
Cidx2 | C | D | |
Ridx1 | Ridx2 | ||
M | id_1 | 100.00 | 0.40 |
id_2 | 1.87 | -0.98 | |
id_3 | -0.10 | 0.41 | |
F | id_1 | 0.76 | 0.12 |
id_2 | 1.49 | -0.21 | |
id_3 | -2.55 | 0.65 |
- iloc 인덱서는 튜플 형태의 다중 인덱스 사용이 불가능하다.
df4["A"]
Cidx2 | C | D | |
---|---|---|---|
Ridx1 | Ridx2 | ||
M | id_1 | 100.00 | 0.40 |
id_2 | 1.87 | -0.98 | |
id_3 | -0.10 | 0.41 | |
F | id_1 | 0.76 | 0.12 |
id_2 | 1.49 | -0.21 | |
id_3 | -2.55 | 0.65 |
-
다중 인덱스가 존재하는데 그냥 인덱싱하면 가장 상위의 인덱스 레벨로 판단하고 출력한다.
-
따라서 두 번째 레벨의 인덱스 값을 넣으면 애러가 발생한다.
df4.loc["M"]
Cidx1 | A | B | ||
---|---|---|---|---|
Cidx2 | C | D | C | D |
Ridx2 | ||||
id_1 | 100.00 | 0.40 | 0.98 | 2.24 |
id_2 | 1.87 | -0.98 | 0.95 | -0.15 |
id_3 | -0.10 | 0.41 | 0.14 | 1.45 |
-
loc 인덱서에서도 그냥 인덱싱하면 가장 상위의 인덱스 레벨로 판단하고 출력한다.
-
loc인덱서는 하나의 인덱싱은 행이 기준임을 한번 더 확인하자.
# 다중 인덱스에서 데이터 추가 - 행 추가
df4.loc[("All", "All"), :] = df4.sum()
df4
Cidx1 | A | B | |||
---|---|---|---|---|---|
Cidx2 | C | D | C | D | |
Ridx1 | Ridx2 | ||||
M | id_1 | 100.00 | 0.40 | 0.98 | 2.24 |
id_2 | 1.87 | -0.98 | 0.95 | -0.15 | |
id_3 | -0.10 | 0.41 | 0.14 | 1.45 | |
F | id_1 | 0.76 | 0.12 | 0.44 | 0.33 |
id_2 | 1.49 | -0.21 | 0.31 | -0.85 | |
id_3 | -2.55 | 0.65 | 0.86 | -0.74 | |
All | All | 101.47 | 0.39 | 3.68 | 2.28 |
- 다중 인덱스에서 데이터 추가 역시 튜플 형식으로 지정해준다.
df4.loc[("M", slice(None)), ("A",slice(None))]
Cidx1 | A | ||
---|---|---|---|
Cidx2 | C | D | |
Ridx1 | Ridx2 | ||
M | id_1 | 100.00 | 0.40 |
id_2 | 1.87 | -0.98 | |
id_3 | -0.10 | 0.41 |
-
만약 상위 레벨의 인덱스는 선택하고 해당 인덱스의 하위 레벨을 모두 출력하고 싶다면
slice(None)
을 사용한다. -
위 예시는 행 인덱스는 M의 하위 레벨을 모두 포함하고, 열 인덱스는 A의 하위 레벨을 모두 포함해서 출력한다.
-
일반적으로 콜론(:)을 사용한 반면 다중 인덱스에선
slice(None)
을 사용하여야 한다는 것을 기억하자.
다중 인덱스의 인덱스 순서 교환
# 행 인덱스 레벨 교환
df5 = df4.swaplevel("Ridx1", "Ridx2")
df5
Cidx1 | A | B | |||
---|---|---|---|---|---|
Cidx2 | C | D | C | D | |
Ridx2 | Ridx1 | ||||
id_1 | M | 100.00 | 0.40 | 0.98 | 2.24 |
id_2 | M | 1.87 | -0.98 | 0.95 | -0.15 |
id_3 | M | -0.10 | 0.41 | 0.14 | 1.45 |
id_1 | F | 0.76 | 0.12 | 0.44 | 0.33 |
id_2 | F | 1.49 | -0.21 | 0.31 | -0.85 |
id_3 | F | -2.55 | 0.65 | 0.86 | -0.74 |
All | All | 101.47 | 0.39 | 3.68 | 2.28 |
-
swaplevel(i, j)
는 인덱스 i와 j를 교환하여 레벨이 변경된다. -
여기서 axis는 0이 디폴트이고 일반적으로 0이 열인데 반해 이 함수에선 행을 의미한다.
# 열 인덱스 레벨 교환
df6 = df4.swaplevel(0,1, axis=1)
df6
Cidx2 | C | D | C | D | |
---|---|---|---|---|---|
Cidx1 | A | A | B | B | |
Ridx1 | Ridx2 | ||||
M | id_1 | 100.00 | 0.40 | 0.98 | 2.24 |
id_2 | 1.87 | -0.98 | 0.95 | -0.15 | |
id_3 | -0.10 | 0.41 | 0.14 | 1.45 | |
F | id_1 | 0.76 | 0.12 | 0.44 | 0.33 |
id_2 | 1.49 | -0.21 | 0.31 | -0.85 | |
id_3 | -2.55 | 0.65 | 0.86 | -0.74 | |
All | All | 101.47 | 0.39 | 3.68 | 2.28 |
다중 인덱스가 있는 경우의 정렬
df5.sort_index(level=0)
Cidx1 | A | B | |||
---|---|---|---|---|---|
Cidx2 | C | D | C | D | |
Ridx2 | Ridx1 | ||||
All | All | 101.47 | 0.39 | 3.68 | 2.28 |
id_1 | F | 0.76 | 0.12 | 0.44 | 0.33 |
M | 100.00 | 0.40 | 0.98 | 2.24 | |
id_2 | F | 1.49 | -0.21 | 0.31 | -0.85 |
M | 1.87 | -0.98 | 0.95 | -0.15 | |
id_3 | F | -2.55 | 0.65 | 0.86 | -0.74 |
M | -0.10 | 0.41 | 0.14 | 1.45 |
-
다중 인덱스가 존재한다면 정렬시에 level 옵션을 사용한다.
-
여기서도 axis는 0이 디폴트이고 행을 의미한다.
# 열 인덱스 기준 정렬
df6.sort_index(axis=1, level=0)
Cidx2 | C | D | |||
---|---|---|---|---|---|
Cidx1 | A | B | A | B | |
Ridx1 | Ridx2 | ||||
M | id_1 | 100.00 | 0.98 | 0.40 | 2.24 |
id_2 | 1.87 | 0.95 | -0.98 | -0.15 | |
id_3 | -0.10 | 0.14 | 0.41 | 1.45 | |
F | id_1 | 0.76 | 0.44 | 0.12 | 0.33 |
id_2 | 1.49 | 0.31 | -0.21 | -0.85 | |
id_3 | -2.55 | 0.86 | 0.65 | -0.74 | |
All | All | 101.47 | 3.68 | 0.39 | 2.28 |
연습 문제 4.5.2
A 반 학생 5명과 B반 학생 5명의 국어, 영어, 수학 점수를 나타내는 데이터프레임을 다음과 같이 만든다.
-
“반”, “번호”, “국어”, “영어”, “수학” 을 열로 가지는 데이터프레임
df_score3
을 만든다. -
df_score3
을 변형하여 1차 행 인덱스로 “반”을 2차 행 인덱스로 “번호”을 가지는 데이터프레임df_score4
을 만든다. -
데이터 프레임
df_score4
에 각 학생의 평균을 나타내는 행을 오른쪽에 추가한다. -
df_score3
을 변형하여 행 인덱스로 “번호”를, 1차 열 인덱스로 “국어”, “영어”, “수학”을, 2차 열 인덱스로 “반”을 가지는 데이터프레임df_score5
을 만든다. -
데이터 프레임
df_score5
에 각 반별 각 과목의 평균을 나타내는 행을 아래에 추가한다.
# 기초 배열 생성
np.random.seed(93)
data = []
for i in range(10):
if i <=4:
data.append( ["A",i+1] + list(np.random.randint(0,101,size=3)) )
else:
data.append( ["B",i+1] + list(np.random.randint(0,101,size=3)) )
data
[['A', 1, 37, 91, 4],
['A', 2, 24, 79, 97],
['A', 3, 85, 48, 77],
['A', 4, 52, 52, 51],
['A', 5, 21, 49, 74],
['B', 6, 33, 8, 71],
['B', 7, 80, 88, 9],
['B', 8, 55, 11, 5],
['B', 9, 44, 43, 46],
['B', 10, 15, 32, 91]]
# 1. df_score3 생성
df_score3 = pd.DataFrame(
data, columns = ["반", "번호", "국어", "영어", "수학"]
)
df_score3
반 | 번호 | 국어 | 영어 | 수학 | |
---|---|---|---|---|---|
0 | A | 1 | 37 | 91 | 4 |
1 | A | 2 | 24 | 79 | 97 |
2 | A | 3 | 85 | 48 | 77 |
3 | A | 4 | 52 | 52 | 51 |
4 | A | 5 | 21 | 49 | 74 |
5 | B | 6 | 33 | 8 | 71 |
6 | B | 7 | 80 | 88 | 9 |
7 | B | 8 | 55 | 11 | 5 |
8 | B | 9 | 44 | 43 | 46 |
9 | B | 10 | 15 | 32 | 91 |
# 2. df_score3을 변형하여 1차 행 인덱스로 "반", 2차 행 인덱스로 "번호"을 가지는 데이터프레임 df_score4
df_score4 = df_score3.set_index(["반","번호"])
df_score4
국어 | 영어 | 수학 | ||
---|---|---|---|---|
반 | 번호 | |||
A | 1 | 37 | 91 | 4 |
2 | 24 | 79 | 97 | |
3 | 85 | 48 | 77 | |
4 | 52 | 52 | 51 | |
5 | 21 | 49 | 74 | |
B | 6 | 33 | 8 | 71 |
7 | 80 | 88 | 9 | |
8 | 55 | 11 | 5 | |
9 | 44 | 43 | 46 | |
10 | 15 | 32 | 91 |
# 3. df_score4에 각 학생의 평균을 나타내는 행을 오른쪽에 추가한다.
df_score4["mean_score"] = round(df_score4.mean(axis=1),2)
df_score4
국어 | 영어 | 수학 | mean_score | ||
---|---|---|---|---|---|
반 | 번호 | ||||
A | 1 | 37 | 91 | 4 | 44.00 |
2 | 24 | 79 | 97 | 66.67 | |
3 | 85 | 48 | 77 | 70.00 | |
4 | 52 | 52 | 51 | 51.67 | |
5 | 21 | 49 | 74 | 48.00 | |
B | 6 | 33 | 8 | 71 | 37.33 |
7 | 80 | 88 | 9 | 59.00 | |
8 | 55 | 11 | 5 | 23.67 | |
9 | 44 | 43 | 46 | 44.33 | |
10 | 15 | 32 | 91 | 46.00 |
# 4. df_score3을 변형하여 행 인덱스로 "번호"를, 1차 열 인덱스로 "국어", "영어", "수학"을,
# 2차 열 인덱스로 "반"을 가지는 데이터프레임 df_score5을 만든다.
temp = df_score3.set_index(["번호","반"])
df_score5 =temp.unstack("반").sort_index(level=0)
df_score5
국어 | 영어 | 수학 | ||||
---|---|---|---|---|---|---|
반 | A | B | A | B | A | B |
번호 | ||||||
1 | 37.0 | NaN | 91.0 | NaN | 4.0 | NaN |
2 | 24.0 | NaN | 79.0 | NaN | 97.0 | NaN |
3 | 85.0 | NaN | 48.0 | NaN | 77.0 | NaN |
4 | 52.0 | NaN | 52.0 | NaN | 51.0 | NaN |
5 | 21.0 | NaN | 49.0 | NaN | 74.0 | NaN |
6 | NaN | 33.0 | NaN | 8.0 | NaN | 71.0 |
7 | NaN | 80.0 | NaN | 88.0 | NaN | 9.0 |
8 | NaN | 55.0 | NaN | 11.0 | NaN | 5.0 |
9 | NaN | 44.0 | NaN | 43.0 | NaN | 46.0 |
10 | NaN | 15.0 | NaN | 32.0 | NaN | 91.0 |
-
번호가 1이고 B반인 학생은 없으므로 값이 NaN으로 뜬다.
-
다른 NaN 값도 같은 경우이다.
-
이 값을 0으로 대체하기엔 없는 학생의 점수를 0점으로 부여하는 것이라 그냥 두었다.
# 5. 데이터 프레임 df_score5에 각 반별 각 과목의 평균을 나타내는 행을 아래에 추가한다.
df_score5.loc["평균",:] = df_score5.mean()
df_score5
국어 | 영어 | 수학 | ||||
---|---|---|---|---|---|---|
반 | A | B | A | B | A | B |
번호 | ||||||
1 | 37.0 | NaN | 91.0 | NaN | 4.0 | NaN |
2 | 24.0 | NaN | 79.0 | NaN | 97.0 | NaN |
3 | 85.0 | NaN | 48.0 | NaN | 77.0 | NaN |
4 | 52.0 | NaN | 52.0 | NaN | 51.0 | NaN |
5 | 21.0 | NaN | 49.0 | NaN | 74.0 | NaN |
6 | NaN | 33.0 | NaN | 8.0 | NaN | 71.0 |
7 | NaN | 80.0 | NaN | 88.0 | NaN | 9.0 |
8 | NaN | 55.0 | NaN | 11.0 | NaN | 5.0 |
9 | NaN | 44.0 | NaN | 43.0 | NaN | 46.0 |
10 | NaN | 15.0 | NaN | 32.0 | NaN | 91.0 |
평균 | 43.8 | 45.4 | 63.8 | 36.4 | 60.6 | 44.4 |
Leave a comment