Data_Analysis_Track_33/Python

Python_Pandas_06(DataFrame 재구조화)

lsc99 2023. 9. 20. 11:29

정돈된 데이터 (Tidy data) 개요
- 대부분 실행환경에서의 많은 데이터 셋은 세부적 분석을 작업을 하기 전에 상당한 양의 데이터 재구성을 할 필요가 있다. - 경우에 따라서는 전체 프로젝트 자체가 오로지 다른 사람들이 사용하기 쉬운 형태로 데이터를 재구성하는 일일 경우도 있다.

- 데이터 재구성의 목적은 정돈된 데이터(tidy data) 를 만드는 것이다.
- Tidy data란 용어는 해들리 위컴이 분석이 용이한 형태로 구성되 있는 데이터셋을 설명하기 위해 만든 용어이다.

 

 

- DataFrame의 구조 변경을 위한 메소드

  • stack()
  • melt()
  • unstack()
  • pivot()
  • pivot_table()
  • crosstab()
  • 텍스트 분해를 위한 str accessor
  • 정돈된 데이터를 다듬는 메소드
  • rename()
  • rename_axis()
  • reset_index()
  • set_index()

stack()
- 컬럼명을 index(행명)으로 전환
    - 기존 index가 있으면 하위 레벨로 들어간다. (기존 것이 상위 레벨)
- 컬럼명을 컬럼의 값으로 전치시킬때도 사용할 수 있다.
- 매개변수
    - dropna=False : 처리 시 생성되는 NA(결측치)는 제거되지 않게 한다. (default: True => 제거)

 

import pandas as pd
import numpy as np

df = pd.read_csv('data/state_fruit.csv', index_col = 0)
df

 

s1 = df.stack() # column을 index로 바꾼다 -> stack()
s1 = s1.to_frame('Count') # Series -> Dataframe (Series의 index -> DF index, value -> column)
                     # args로 문자열 -> 컬럼명, (생략시 컬럼명 : 0)
tidy_df = s1.reset_index()     # index name을 컬럼으로 변경
tidy_df.columns = ['state', 'fruit', 'count']
tidy_df

series/dataframe.rename_axis() -> index 축 이름, column 축 이름을 변경/ [index/column 이름의 이름.]

df.stack().rename_axis(['state', 'fruit']).reset_index(name = 'count')

unstack()
- stack() 반대로 index를 컬럼으로 변환한다.
- 매개변수
    - level: multi-index일 경우 컬럼으로 만들 레벨을 지정한다. 기본값은 -1 로 가장 안쪽의 index를 이동시킨다.

 

s = tidy_df.set_index(['state', 'fruit'])
s.unstack()
s.unstack(level=0)

 

# droplevel(level, exis) # 컬럼이나 index 명이 mulit index일때 특정 level의 것을 제거 메소드
s.unstack().droplevel(level=0, axis=1)

melt() - 컬럼명을 컬럼의 값으로 변환한다.
- 컬럼 명을 단일 컬럼의 값으로 변환한다.
- 변환할 컬럼들을 지정할 수 있어 stack()보다 더 유연하다.

 

매개변수
- id_vars: 값으로 변환하지 않고 그대로 유지하고자 하는 컬럼명(열이름)들의 리스트
    - 식별변수라고도 한다.
    - 지정한 변수(컬럼)은 같은 열에 남게 되지만, value_vars에 전달된 각 열에 대해 반복적으로 나타난다.
- value_vars: 단일 컬럼의 값으로 변경하고자 하는 컬럼명 리스트
    - value_vars에 지정한 컬럼이 value가 되고 그 컬럼의 값들은 다른 컬럼으로 생성된다.
    - id_vars를 지정하지 않고 value_vars만 지정하면 value_vars에 지정 안된 컬럼은 제거된다.
        - 제거 되지 않고 단독 컬럼으로 유지되길 바라는 컬럼은 id_vars로 지정한다.
- var_name: value_vars로 단일열이 된 열의 이름 지정(지정 안하면 컬럼명은 variable)
- value_name: value_vars에 지정된 열들의 값들이 변환된 컬럼의 이름 지정(지정안하면 컬럼명은 value)

 

- melt 한 경우 index명은 무시된다. => RangeIndex로 대체된다.
    - index를 유지하려면 reset_index를 이용해 value로 뺀 뒤 해야 한다.
- stack은 열이름을 index명으로 정돈(변경) 한다.

 

df2 = df.rename_axis(index='state').reset_index()
df2

 

df2.melt(id_vars=['state'], # 컬럼으로 그대로 유지
         value_vars = ['Apple', 'Orange', 'Banana'], # 컬럼의 값으로 내릴 컬럼명을 지정.
         var_name = 'fruit', # 컬럼명을 값으로 가지는 컬럼의 이름. (생략 : variable)
         value_name = 'count', # 값들을 값으로 가지는 컬럼의 이름. (생략 : value)
        )

 

# id_vars를 생략하면 value_vars에 지정한 컬럼들 이외는 제거. (state, banana가 제거됨.)
df2.melt(value_vars = ['Apple', 'Orange'])

 

# id_vars만 설정한 경우 id_vars에 지정안된 모든 컬럼들이 variable의 값으로 돌아간다.
df3 = df2.melt(id_vars=['state'])
df3

pivot - index, column, value가 될 컬럼들을 지정해 재구조화
- 데이터프레임 재구조화가 목적
- 데이터 프레임에서 두개이상의 범주형 변수를 그룹으로 묶어 특정 값을 보려고 할때 사용할 수 있다.
    - pivot_table은 그룹으로 묶은 뒤 특정 변수의 통계량을 본다면 pivot은 그 값을 그대로 본다.
- melt()된 것을 원상복구 시킬때도 사용할 수 있다.


pivot 매개변수
- index: 문자열. 행이름으로 사용할 컬럼 -> 열이 index로 이동하는 형태가 된다.
- columns: 문자열. 컬럼명으로 사용할 컬럼
- values : Value에 올 컬럼명

 

df3.columns = ['state', 'fruit', 'count']
df3

 

df3.pivot(index = 'state', columns = 'fruit', values = 'count')

 

df3.pivot_table(index = 'state', columns = 'fruit', values = 'count')

crosstab() : 범주형 값들 고유값 별 빈도표를 만든다.

 

  • 매개변수
  • index: 행에 들어올 1차원 배열
  • columns: 열에 들어올 1차원 배열
  • rownames: index 이름 지정. 생략하면 index의 고유값들로 설정된다.
  • colnames: column 이름 지정. 생략하면 columns의 고유값들로 설정된다.
  • margins: 총합계 행과 열을 추가할지 여부. True-추가, False-추가안함(기본값)
  • normalize: 빈도수를 비율로 나타낸다.
# 10 : 학생, 자영업, 회사원
job = ['학생', '자영업', '자영업', '회사원', '회사원', '학생', '자영업', '자영업', '회사원', '회사원']
# 10 : pass, fail
pass_yn = ['pass', 'fail', 'fail', 'fail', 'pass', 'pass', 'fail', 'fail', 'fail', 'pass']
df = pd.DataFrame({
    'job' : job,
    'pass': pass_yn
})
df

 

df['job'].value_counts()

df['pass'].value_counts()

 

df.groupby(['job', 'pass'])['job'].count()

 

pd.crosstab(index = df['job'], columns = df['pass'])

pd.crosstab(index=df['job'], columns = df['pass'])
pd.crosstab(index=df['job'], columns = df['pass'], margins=True)
pd.crosstab(index=df['job'], columns = df['pass'], normalize=True) # 비율
pd.crosstab(index=df['job'], columns = df['pass'], normalize=True, margins=True)

 

pd.crosstab(job, pass_yn, rownames=['직업'], colnames=['통과여부'])

diamonds.csv 파일 불러오기

dia = pd.read_csv('data/diamonds.csv')
dia.info()

 

pd.crosstab([dia['cut'], dia['clarity']], dia['color'], margins=True, normalize=True)