DataFrame 재구조화

Bleu·2023년 9월 20일
0

python

목록 보기
15/22

정돈된 데이터란?

  • 변수(데이터의 속성)는 열을 형성
  • 관측값(하나의 데이터)은 행을 형성
  • 관측 단위별로 별도의 테이블(표)을 구성
    → 단일 관측

변수, 관측값, 관측단위

  • 변수

    • Feature, 컬럼, 속성

    • 데이터를 구성하는 요소들

    • 변수 이름
      → 성별, 인종, 연봉, 직위 같은 레이블

    • 변수 값
      → 관측 때마다 달라지는 값
      : 각 변수가 가질 수 있는 값

      • ex)
        → 성: 남성/여성
        → 인종: 황인/흑인/백인
        → 연봉: 삼천만원, 사천만원...
        → 키: 100.0 ~ 250.0
  • 단일 관측

    : 하나의 관측단위, 하나의 데이터
    → DataFrame(Pandas), Table(데이터베이스), Table(엑셀)로 표현

    • 변수 : 단일 관측 대상은 여러개의 속성들로 구성 (이때의 속성)
      • 단일 관측은 하나의 데이터 대한 모든 변수(속성)들의 모음
    • 예)
      • 고객, 제품, 계좌
    • 종업원정보(근무시간같은)와 고객정보(구매 액수)를 같은 테이블에 병합하는 것은 단일 관측이라 할수 없음. -> 정돈된 데이터의 원칙에 위배됨

정돈되지 않은 데이터의 가장 흔한 형태

  1. 열 이름이 변수 이름이 아니라 값인 경우
  2. 열 이름에 복수 개의 변수가 저장된 경우
  3. 변수가 행과 열에 모두 저장된 경우
  4. 같은 테이블에 복수의 관측단위가 저장된 경우
    → 하나의 테이블에 여러 데이터(관측단위)가 병합된 것
  5. 단일 관측 단위가 복수 테이블에 저장된 경우
    → 하나의 데이터의 변수들이 여러 테이블에 나눠 저장된 경우

데이터를 정돈한다의 의미

(단순히 데이터셋의 값을 바꾸거나 결측치를 채운다는 것은 아님)
: 데이터를 정돈하는 것은 데이터의 형태나 구조를 정돈 원칙에 맞게 변형시키는 것

  • 데이터가 올바른 형태로 주어진다면 분석이 쉬워짐
  • 다양한 형태의 조회에 적용할 수 있도록 데이터셋을 만들어 줌

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 => 제거)

ex)

import numpy as np
import pandas as pd

df = pd.read_csv("data/state_fruit.csv", index_col = 0)
df
# column -> index
s1 = df.stack()
s1.to_frame("Count")  #Series -> DataFrame (Series의 index-> DF index, value -> column)
                        # args로 문자열 -> 컬럼명 (생략시 컬럼명:0)
tidy_df = s1.reset_index()  #index name 을 컬럼으로 지정
tidy_df.columns = ["stste", "fruit", "count"]
tidy_df

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

df.stack().rename_axis(["start", "fruit"])

df.stack().rename_axis(["start", "fruit"]).reset_index(name = "count") 

위의 코드에서 아래 코드로 변경 시 원래 있던 값엣다가 컬텀명 "count"를 붙여줌


unstack()

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

ex)

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

droplevel(level, axis) : column이나 index명이 multi index 일 떄 특정 level의 것을 제거 메소드


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

-> STATE 유지

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

id_vars를 생략하면 value_vars에 지정한 철럼들 이외는 제거 (state, banana가 제거됨)

df3 = df2.melt(id_vars = ['state'])
df3

id_var만 설정. id_vars에 지정 안된 모든 컬럼들이 variable의 값으로 들어감



pivot - index, column, value가 될 컬럼들을 지정해 재구조화

목적 : 데이터프레임 재구조화

  • 데이터 프레임에서 두개이상의 범주형 변수를 그룹으로 묶어 특정 값을 보려고 할때 사용 가능
    → pivot_table은 그룹으로 묶은 뒤 특정 변수의 통계량을 본다면 pivot은 그 값을 그대로 봄
    → melt()된 것을 원상복구 시킬때도 사용가능

pivot 매개변수

  • index: 문자열. 행이름으로 사용할 컬럼 -> 열이 index로 이동하는 형태가 됨
  • columns: 문자열. 컬럼명으로 사용할 컬럼
  • values : Value에 올 컬럼명

ex)

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

그냥 이대로 보면 너무 길어지기 떄문에

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

열 이름을 죄측에 행으로 변횐해서 넣음

count값을 집계해서 넣을건지 그냥 넣을건지가 pivot과 pivot table의 차이


crosstab()

: 범주형 값들을 고유값 별 빈도표로

매개변수

  • index: 행에 들어올 1차원 배열

  • columns: 열에 들어올 1차원 배열

  • rownames: index 이름 지정. 생략하면 index의 고유값들로 설정된다.

  • colnames: column 이름 지정. 생략하면 columns의 고유값들로 설정된다.

  • margins: 총합계 행과 열을 추가할지 여부. True-추가, False-추가안함(기본값)

  • normalize: 빈도수를 비율로 나타낸다.

ex)

job = ['학생', '자영업', '자영업','회사원', '회사원', '학생', '자영업', '자영업', '회사원', '회사원']
pass_yn = ['pass', 'fail', 'pass', 'fail' , 'pass', 'pass', 'fail', 'pass', 'fail', 'pass']
df = pd.DataFrame({
    "job": job,
    "pass": pass_yn
})
df

이러한 데이터가 있다고 가정

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

최종적으로 이러한 table 이 만들어 짐

이는 pivor table과 유사하나 pivot table에서 빈도수를 세는것을 제외했다고 보면 됨

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

그리고 이처럼 뒤에 margins = True를 붙여주면 중간 집계를 확인 할 수 있음

실행 시 이러한 결과 도출

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

그리고 margin 대신 normalize를 사용한다면 결과값이 비율로 바뀌어 이러한 결과를 얻게 됨

rownamescolnames 사용 시 행이나 열의 이름 변경 가능

0개의 댓글