[pandas] DataFrame
😸 pandas.DataFrame ?
- 생성된 instance의 크기의 변경이 가능한 2차원 배열
- 구조: class pandas.DataFrame(data=None, index=None, columns=None, copy=None)
- parameter
- index : instance에 설정되는 행 레이블
- columns : instance에 설정되는 열 레이블
- dtype : dtype 데이터 유형을 강제하고자 할 때 값
( 기본값은 None이며 None일 경우 type이 자동으로 추론)
👉 축 및 레이블
- 인덱스를 열로 변환 (reset_index)
- 설정 인덱스를 제거하고 기본 인덱스 (0,1,2, ...n)으로 변경하는 메서드
- 구조 : DataFrame.reset_index(level=None, drop=False, inplace=False, col_level=0, col_fill='')
- level : Multi index의 경우 제거할 인덱스의 레벨을 설정할 수 있습니다.
- drop : 제거한 인덱스를 열에 추가할지 여부입니다. 기본값은 False로 제거된 인덱스는 열로 변환됩니다.
- inplace : pandas 공통 인수로, 원본을 변경할 지 여부입니다.
- col_level / col_fill : Multi index의 경우 제거된 인덱스를 열에 추가할 때 레벨과 열의 이름을 설정할 수 있습니다.
( col_level을 통해 레벨을 설정하고, col_fill을 통해 해당 열의 이름을 정합니다.)
예시로 3*2 객체를 생성하겠습니다.
df = pd.DataFrame([[1,2],[3,4],[5,6]],['row1','row2','row3'],['col1','col2'])
print(df)
> col1 col2
row1 1 2
row2 3 4
row3 5 6
기본적으로 아무 인수 없이 사용할 경우, 모든 레벨에 대해 인덱스가 제거되며 열에 추가됩니다.
print(df.reset_index())
index col1 col2 # index라는 열이 생성되고 기존 인덱스가 기본 인덱스로 변경됨
0 row1 1 2
1 row2 3 4
2 row3 5 6
drop = True인 경우 열이 완전히 삭제됩니다.
print(df.reset_index(drop=True))
> col1 col2
0 1 2
1 3 4
2 5 6
inplace = True인 경우 원본이 변경됩니다.
df.reset_index(inplace=True)
print(df)
> index col1 col2
0 row1 1 2
1 row2 3 4
2 row3 5 6
👉 Multi Index
예시로 4*4 Multi Index를 생성하겠습니다.
idx = [['IDX1','IDX1','IDX2','IDX2'],['row1','row2','row3','row4']]
col = [['COL1','COL1','COL2','COL2'],['val1','val2','val3','val4']]
data = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
df2 = pd.DataFrame(data,idx,col)
print(df2)
> COL1 COL2
val1 val2 val3 val4
IDX1 row1 1 2 3 4
row2 5 6 7 8
IDX2 row3 9 10 11 12
row4 13 14 15 16
Multi Index의 경우 level을 설정해줌으로 제거할 인덱스의 레벨을 선택할 수 있습니다.
level을 입력하지 않은 경우 모든 index에 대해서 수행하게 됩니다.
print(df2.reset_index())
>level_0 level_1 COL1 COL2
val1 val2 val3 val4
0 IDX1 row1 1 2 3 4
1 IDX1 row2 5 6 7 8
2 IDX2 row3 9 10 11 12
3 IDX2 row4 13 14 15 16
# level=0 일 경우
print(df2.reset_index(level=0))
> level_0 COL1 COL2
val1 val2 val3 val4
row1 IDX1 1 2 3 4
row2 IDX1 5 6 7 8
row3 IDX2 9 10 11 12
row4 IDX2 13 14 15 16
# level=1 일 경우
print(df2.reset_index(level=1))
> level_1 COL1 COL2
val1 val2 val3 val4
IDX1 row1 1 2 3 4
IDX1 row2 5 6 7 8
IDX2 row3 9 10 11 12
IDX2 row4 13 14 15 16
- col_fill / col_level 사용
col_fill 이용하여 열로 변경되는 인덱스의 열 이름을 설정할 수 있습니다.
print(df2.reset_index(level=1, col_fill ='COL0'))
> level_1 COL1 COL2
COL0 val1 val2 val3 val4 #COL0이 열 이름으로 생성됨.
IDX1 row1 1 2 3 4
IDX1 row2 5 6 7 8
IDX2 row3 9 10 11 12
IDX2 row4 13 14 15 16
# col_level로 열 이름의 레벨 정할 수 있음.
print(df2.reset_index(level=1, col_fill='COL0', col_level=1))
> COL0 COL1 COL2
level_1 val1 val2 val3 val4
IDX1 row1 1 2 3 4
IDX1 row2 5 6 7 8
IDX2 row3 9 10 11 12
IDX2 row4 13 14 15 16
👉 응용하기
# 필요한 data 사이트에서 불러오기
import pandas as pd
url = "https://raw.githubusercontent.com/pandas-dev/pandas/main/doc/data/titanic.csv"
titanic = pd.read_csv(url)
titanic.head(1)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund male 22.0 1 0 A/5 21171 7.25 NaN S
group by를 이용하여 필요한 data를 뽑습니다.
# 성별에 따른 평균 나이
grouped = titanic.groupby("Sex")["Age"].agg("mean")
grouped
> Sex
female 27.915709
male 30.726645
Name: Age, dtype: float64
# Groupby에서 컬럼을 추가
# 원하는 컬럼과 수식을 딕셔너리로 묶어서 관리하는 것이 편하다.
agg_dict = {'Age':'mean', 'Fare':'median'}
grouped = titanic.groupby('Sex').agg(agg_dict)
grouped
> Age Fare
Sex
female 27.915709 23.0
male 30.726645 10.5
# Fare에서 중간값, 평균값을 구하기
agg_dict = {'Age':'mean', 'Fare': ['median','sum']}
grouped = titanic.groupby('Sex').agg(agg_dict)
grouped
> Age Fare
mean median sum
Sex
female 27.915709 23.0 13966.6628
male 30.726645 10.5 14727.2865
이 때, Mutli index를 단일로 만들어 주도록하겠습니다.
agg_dict = {"Age" : "mean", "Fare": "median"}
grouped = titanic.groupby("Sex").agg(agg_dict)
result = grouped.reset_index()
print(result)
> Sex Age Fare
0 female 27.915709 23.0
1 male 30.726645 10.5
여기서, columns, values, keys, levels의 용어에 대해 제대로 이해해야 합니다.
print(type(grouped)) # grouped의 type 확인
print(grouped.columns) # MultiIndex 객체를 반환
print(type(grouped.columns))
> <class 'pandas.core.frame.DataFrame'>
Index(['Age', 'Fare'], dtype='object')
<class 'pandas.core.indexes.base.Index'>
print(grouped.columns.values) # numpy 배열을 반환
print(type(grouped.columns.values)) # type 확인
> ['Age' 'Fare']
<class 'numpy.ndarray'>
grouped.columns는 Multi Index 객체를 반환하며, grouped.columns.values는 numpy 배열을 반환하게 됩니다.
agg_dict = {'Age': 'mean', 'Fare' : ['median', 'sum']}
grouped = c.groupby('Sex').agg(agg_dict)
print(grouped)
> Age Fare
mean median sum
Sex
female 27.915709 23.0 13966.6628
male 30.726645 10.5 14727.2865
print(grouped.columns.values)
> [('Age', 'mean') ('Fare', 'median') ('Fare', 'sum')]
print(grouped.columns)
> MultiIndex([( 'Age', 'mean'),
('Fare', 'median'),
('Fare', 'sum')],
)
print(grouped.columns.keys)
print(grouped.columns.levels)
> AttributeError: 'MultiIndex' object has no attribute 'keys'
> [['Age', 'Fare'], ['mean', 'median', 'sum']]
grouped.columns.keys()는 pandes index 객체에 대해 호출되는 메소드로 groupby 결과로 생성된 MultiIndex 객체 키 값을 반환합니다. 따라서 grouped.columns.keys()는 'grouped' DataFrame에서 사용할 수 없습니다.
대신 grouped.columns.levels를 사용하여 MultiIndex 객체의 레벨 값을 반환할 수 있습니다.
다음은 컬럼을 단일로 변경 시켜주는 방법입니다.
# comprehension을 이용하여 단일 컬럼 만들기
agg_dict = {'Age': 'mean', 'Fare' : ['median', 'sum']}
grouped = titanic.groupby('Sex').agg(agg_dict)
grouped.columns = ['_'.join(col).strip() for col in grouped.columns.values]
grouped.reset_index(inplace=True)
print(grouped)
> Sex Age_mean Fare_median Fare_sum
0 female 27.915709 23.0 13966.6628
1 male 30.726645 10.5 14727.2865
# 반복문을 통해서 단일 컬럼 만들기
add_dict = {'Age':'mean','Fare':['median','sum']}
grouped = titanic.groupby('Sex').agg(agg_dict)
new_cols = []
for col in grouped.columns:
if isinstance(col, tuple):
new_col = f'{col[0]}_{col[1]}'
else:
new_col = col
new_cols.append(new_col)
grouped.columns = new_cols
result = grouped.reset_index()
result
> Sex Age_mean Fare_median Fare_sum
0 female 27.915709 23.0 13966.6628
1 male 30.726645 10.5 14727.2865
첫 번째, comprehension을 이용한 방법은 columns.values에서 서로 '_'로 연결해준 후 공백 제거한 후 reset_index를 해준 방법입니다.
두 번째, for문을 이용한 방법은 columns를 tuple 형식으로 변경한 후 '_'로 묶은 후 now_col에 append 해주고 reset_idex를 해준 방법입니다.
방식은 다르나, 두 방법 모두 결과는 같게 나오게 됩니다.