빅데이터 전문가 되기

[pandas] DataFrame 본문

Python/pandas

[pandas] DataFrame

지야소이 2023. 4. 15. 23:18

😸 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.columnsMulti 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를 해준 방법입니다.

방식은 다르나, 두 방법 모두 결과는 같게 나오게 됩니다.

Comments