Data_preprocessing

Numpy와 Pandas에 대해 공부를 진행했었다.

다음과 같이 간단하게 정리 할 수 있는데

Numpy

-> Numerical Python
-> ndarray(다차원 배열)

Pandas

-> Series(1차원), DataFrame(2차원)
==> Numpy의 ndarray를 기반으로 만들어짐
-> DataFrame의 특징, 속성, 생성방법, 함수, indexing과 slicing

이렇게 간단하게 정리 할 수 있을 것이다.

오늘은 DataFrame이 제공하는 분석용 함수

  • 기술분석(Descriptive Analysis) = 서술하다
  • 평균, 표준편차, 분산, 공분산, 상관계수, 사분위 .. 이런걸 한번 알아보도록하자!
  • 예제를 통해 알아보자
import numpy as np
import pandas as pd

data = np.array([[2, np.nan],
                [7, -3],
                [np.nan, np.nan],
                [1, -2]])
print(data)
# [[ 2. nan]
#  [ 7. -3.]
#  [nan nan]
#  [ 1. -2.]]

df = pd.DataFrame(data,
                  columns=['one','two'],
                  index=['a','b','c','d'])

display(df)
#   	one	two
# a	    2.0	NaN
# b	    7.0	-3.0
# c	    NaN	NaN
# d	    1.0	-2.0

# 합을 함 구해볼거다 numpy 경우 축(axis)을 정해줘야 축끼리 계산이 된다. 아니면 전체를 더하게 된다.
# 
# print(df.sum())         # DataFrame의 경우만약 axis를 지정하지 않으면  axis=0 default.로 사용
                        # 기본속성으로 dropna=True가 default
  
# print(df.sum(axis=1))
# a    2.0
# b    4.0
# c    0.0
# d   -1.0
# print(df['two'].sum()) # Series에 대해서도 집계함수를 사용할 수 있어요! 
# -5.0
  • Pandas는 그래프 도구를 내장하고 있어요
  • 이 기능들은 matplotlib으로투버 차용
  • 그래서 Pandas의 그래프 도구를 사용하는 것보다는
    maplotlib를 배워서 사용하는게 좋아요





데이터 전처리(Data-pre-processing)

데이터 전처리에 대해 알아보도록하자!

데이터 분석

machine learning, deep learning을 제데로 할려면 뭐가 필요한가?

  1. 데이터의 양
  2. 양질의 데이터가 들어가 있어야 함
  3. 데이터의 품질이 중요
  • Missing value(결측치)
  • Outlier(이상치)
  • 중복데이터(의미 있는 중복인지 쓸모없는 중복인지 판단하여 해결)
  • Data의 단위처리
  • 정규화
    • 집의가치 1억~5억
    • 집의 연식 1년~40년
    • 수치가 1억~5억이 더커서 포커스가 여기에 맞춰짐
      => 이런 데이터들의 처리를 해줘야한다!

예제를 이용해서 전처리를 해보자!
titanic dataset을 이용할 것이다!

  • Seaborn module을 사용하!
    • 그래프를 그리는 모듈이다
    • matplotlib확장버전이라 생각하면 됨
    • 이거를 활용하여 titanic dataset을 이용할 것이다.

데이터 전처리 과정

  1. Missing Value(결치값)
  • DataFrame안에 누락된 값이 존재
  • 데이터 입력시 실수로 누락됬거나, 파일 변환시 처리 문제로 누락된 경우
    -> 결치값은 NaN으로 표현
  • 이런 Missing Value가 많으면 좋지 않음!
    -> 그렇기 때문에 처리를 해야한다
      1. 삭제 : 만약 데이터가 충분히 많다면 그리고 missing value가 전체의 3~4%이내 일 때
      1. 대체 : 평균, 중위, 최대, 최소, 빈도값으로 대체할 수 있다.
      • 머신러닝 기법으로 이 값을 예측해서 채운다!
      • 항상 사용은 불가하고 조건이 있다!
  1. 이상치 처리
  • 이상치를 찾아서 수정
  • 이부분은 나중에 다시 알아보도록 하겠다. 지금은 결측치 처리에 집중하자.
  1. 중복 처리
  • duplicated( )
  • drop_duplicates( )
  • 이 두가지를 통해 처리 할 수 있다.
  1. 자료형 변환
  • 만약 숫자가 문자열(pandas object)로 저장되어 있으면 숫자형으로 범주를 나눠서 카테고리별로 나눠 분류해준다!


이제 예제를 통해 좀 더 알아보도록 하자 일단 anaconda를 통해 seaborn 모듈을 설치해 주도록 하자
conda install seaborn
  1. missing value(결측치)처리
import numpy as np
import pandas as pd
import seaborn as sns

df =sns.load_dataset('titanic')

# display(df)

# 먼저 전체 데이터를 가지고 Missing Value가 존재하는 지 확인
# 이 작업이 먼저 선행되어야 해요!

# print(df.info())
# df['deck'].value_counts()   # 688개의 NaN
# df.isnull().sum(axis=0)
survived         0
pclass           0
sex              0
age            177
sibsp            0
parch            0
fare             0
embarked         2
class            0
who              0
adult_male       0
deck           688
embark_town      2
alive            0
alone            0
dtype: int64

# missing_df = df.isnull()
# for col in df.columns:
#     missing_value = missing_df[col].value_counts()
#     try:
#         print(col, ' :', missing_value[True])
#     except:
#         print(col, ' :', 0)


# 결치값을 삭제해 봐요!
# 일단 먼저 삭제할 column을 결정해서 지워보아요!

# 기본적인 삭제방법
# df2 =df.drop('deck', axis=1, inplace=False)   # 컬럼명을 명시해서 지워줌
# display(df2.head())
# "deck" 컬럼이 사라진걸 확인 할 수 있다.

# 또 다른 컬럼 삭제 방법
# dropna
thresh_df = df.dropna(axis=1, thresh=500, inplace=False) # 컬럼중에 nan이 500개가 넘어가면 지워라 라는 뜻
# display(thresh_df.head())

# 행을 지울 수 있어요!
result_df = thresh_df.dropna(subset=['age'], axis=0, how='any',inplace=False) # 행을 지우는데 age컬럼의 nan이 있으면 지워라
print(result_df.shape)   # (714, 15) 원래는 (891, 15) 이었음
print(result_df.info())

# 컬럼단위로 nan이 많은 값은 날려주고 그다음 행단위로 nan이 있는 값들을 지워준다
  • 결치값을 다른 값으로 대체할려면 어떻게 해야하나요?
import numpy as np
import pandas as pd
import seaborn as sns

# titanic data set loading
df= sns.load_dataset('titanic')
display(df.head())

# age column의 missing value(결측치)를 다른 값으로 대체

# age의 평균 값으로 대체
# mean_age = df['age'].mean()  #  mean은 기본적으로 NaN은 제외하고 평균을 구해요!
# print(mean_age)  # 29,669
# df['age'].fillna(mean_age, inplace=True)
# display(df.head(10))
# fillna를 통해 nan값들을 mean_age로 변경시켜준다!


# embarke 같은 경우에는 빈도를 이용해서 값을 대체하는게 좋아요!
# 데이터 특성상 서로 이웃하고 있는 데이터는 유사성을 가질 확률이 높아요!
# 그래서 자신의 앞이나 뒤의 데이터로 Missing Value를 채우는 방법을 제공!
display(df['embarked'][820:831])
# df['embarked'].fillna(method='ffill', inplace = True)
df['embarked'].fillna(method='bfill', inplace = True)
# 다음과 같이 method=ffill or bfill을 통해 앞이나 뒤의 데이터로 missing value를 채워 줄 수 있어요!
820      S
821      S
822      S
823      S
824      S
825      Q
826      S
827      C
828      Q
829    NaN
830      C
Name: embarked, dtype: object
820    S
821    S
822    S
823    S
824    S
825    Q
826    S
827    C
828    Q
829    C
830    C
Name: embarked, dtype: object

print(df['embarked'][820:831])

이상치의 경우 나중에 알아보도록 했으니 이번엔 중복 처리를 해보자

  1. 중복처리
# 의미가 있는 중복인지 아니면 그냥 중복된 데이터가 존재하는지를 판단
# 만약 의미없는 중복된 데이터가 있으면 제거!

import numpy as np
import pandas as pd
import seaborn as sns

df = pd.DataFrame({'c1':['a','a','b','a','b'],
                   'c2':[1,1,1,2,2],
                   'c3':[1,1,2,2,2]})
display(df)

	c1	c2	c3
0	a	1	1
1	a	1	1
2	b	1	2
3	a	2	2
4	b	2	2
# df.duplicated() # 중복되었니? 라고 물어보는 함수
# dup_df = df.duplicated()  # 한줄한줄 비교하며 확인 Series를 리턴
# print(dup_df)
0    False
1     True
2    False
3    False
4    False
dtype: bool

# duplicated()는 DataFrame에 적용되는데 이걸 Series에도 적용할 수 있어요!
# print(df['c2'].duplicated())
0    False
1     True
2     True
3    False
4     True
Name: c2, dtype: bool
# 위에서부터 한줄씩 비교하면서 결과를 출력

# 중복 데이터를 제거! (모든 컬럼을 다 비교)  drop_duplicates   
# df2 = df.drop_duplicates()
# display(df2)
# 중복데이터를 비교하여 제거함
	c1	c2	c3
0	a	1	1
2	b	1	2
3	a	2	2
4	b	2	2

# 중복데이터를 제거 ( 특정 컬럼만 비교) subset
df2 = df.drop_duplicates(subset=['c2', 'c3'])
display(df2)
	c1	c2	c3
0	a	1	1
2	b	1	2
3	a	2	2
# 이거 또한 위에서 비교하면서 결과를 출력해준다!
  1. 데이터 타입의 변환
# 사용하는 데이터 set은 mpg데이터 셋을 사용할거임
import numpy as np
import pandas as pd
import seaborn as sns

df = pd.read_csv('./data/auto-mpg.csv', header =None) # header = None은 컬럼명이 없다를 명시

# mpg : 연비(mile per gallon)
# cylinders : 실린더 개수
# displacement : 배기량
# horsepower : 마력(출력)
# weight : 중량
# acceleration : 가속능력
# year : 출시년도 (70 => 1970년도)
# origin : 제조국 (1: USA, 2: EU, 3: JPN)
# name : 차량이름
df.columns = ['mpg', 'cylinders','displacement','horsepower',
              'weight', 'acceleration', 'year', 'origin', 'name']

display(df)
# print(df.dtypes)

# horsepower 컬럼은 안에 숫자가 들어가 있는데 type이 object
# 숫자(실수)로 변경하는게 좋을것 같아요!

# df['horsepower']= df['horsepower'].astype('float')
# 다음 문장을 실행하면 오류가난다.. 왜그럴까?
#실수로 바꿀수 없는 무언가가 있어서 오류가 나는것 같다
# print(df['horsepower'].unique())

# ['130.0' '165.0' '150.0' '140.0' '198.0' '220.0' '215.0' '225.0' '190.0'
#  '170.0' '160.0' '95.00' '97.00' '85.00' '88.00' '46.00' '87.00' '90.00'
#  '113.0' '200.0' '210.0' '193.0' '?' '100.0' '105.0' '175.0' '153.0'
#  ...'64.00' '74.00' '116.0' '82.00']
# 값을 확인해보니 '?' 값이 들어가 있다.

# 원래 결측치(missing Value)는 NaN으로 표현되는데 가끔 다른문자('?','-')로 표현하는 경우가 종종 있음!
# 권장되는 방법은 이런 다른 문자로 표현되는 결측치를 NaN으로 변환시켜서
# 우리가 알고 있는 dropna()메소드를 이용해 결측치를 처리!
df['horsepower'].replace('?',np.nan, inplace=True)
# replce를 통해 해당 값을 nan값으로 바꿔준다

# print(df['horsepower'].unique())
df.dropna(subset=['horsepower'], axis=0, inplace=True)
# 열기준이아닌 행을 기준으로 nan값을 제거해야해서 axis = 0인거를 잊지말자
# print(df['horsepower'].unique())

df['horsepower']= df['horsepower'].astype('float')
print(df.dtypes)
mpg             float64
cylinders         int64
displacement    float64
horsepower      float64
weight          float64
acceleration    float64
year              int64
origin            int64
name             object
dtype: object

# origin column의 값을 1, 2, 3에서 USA, EU, JPN으로 변경
df['origin'].replace({1:'USA',
                      2:'EU',
                      3:'JPN'},
                      inplace=True)
display(df.head(3))
# 기존의 origin이 1,2,3으로 표현되는데
# 각각 명시된 거에따라 USA, EU, JPN으로 표현된다!
df['origin']= df['origin'].astype('category')
print(df.dtypes)
mpg              float64
cylinders          int64
displacement     float64
horsepower       float64
weight           float64
acceleration     float64
year               int64
origin          category
name              object
dtype: object
  1. 범주형 데이터 처리
    0~5 : 어린이
    16~25 : 청소년
    26~40:청년
    =>이런형태로 연속적인 데이터를 범주 형 데이터 취지하는게
    훨씬 효율적인 겅우가 있다
    구간 분할
    => 연속적인 데이터를 일정한 구간으로 나누기
    일정한 구간 : Bin

          - bin 1 -                 - bin2 -                 - bin3 -
        |--------------------|------------------------|-----------------------|
      경계1                    경계2                       경계3                     경계 4
import numpy as np
import pandas as pd
import seaborn as sns

df = pd.read_csv('./data/auto-mpg.csv', header =None) # header = None은 컬럼명이 없다를 명시

# mpg : 연비(mile per gallon)
# cylinders : 실린더 개수
# displacement : 배기량
# horsepower : 마력(출력)
# weight : 중량
# acceleration : 가속능력
# year : 출시년도 (70 => 1970년도)
# origin : 제조국 (1: USA, 2: EU, 3: JPN)
# name : 차량이름
df.columns = ['mpg', 'cylinders','displacement','horsepower',
              'weight', 'acceleration', 'year', 'origin', 'name']
display(df)

df['horsepower'].replace('?',np.nan, inplace=True)       # Missing Value 변화
df.dropna(subset=['horsepower'], axis=0, inplace=True)   # Missing Value 삭제
df['horsepower']= df['horsepower'].astype('float')        # 실수로 데이터 타입 변환            
display(df.head(3))

# horsepower를 구간보조에 사용할거도
# ['고출력'],['보통출력'], ['저출력']

count, bin_divider = np.histogram(df['horsepower'],bins=3)
print(count, bin_divider)
[257 103  32] [ 46.         107.33333333 168.66666667 230.        ]


bin_names = ['저출력', '보통출력', '고출력']

df['hp_bin'] = pd.cut(x=df['horsepower'],
                     bins=bin_divider,
                     labels=bin_names,
                     include_lowest=True) # True는 첫 경계값을 포함 시킴

display(df.head(100))

# 이런 카테고리를 나타내는 범주형 데이터는 머신러닝 알고리즘에서 바로 사용하기 힘들어요!
# - 컴퓨터가 인식 할 수 있는 형태로 제공해줘야함
# 이문제를 해결하기위해 사용하는게 dummy variable(더미변수) == 0과 1로 표현하고 해당 특성이 있는지 없는지를 표현

# ==> one - hot -encoding

horsepower_dummy = pd.get_dummies(df['hp_bin'])
display(horsepower_dummy.head(5))
	저출력	보통출력	고출력
0		0	  	1	    0
1		0		1		0
2		0		1		0
3		0		1		0
4		0		1		0
  1. 정규화 ( Normalization )
  • DataFrame의 각 열이 가지고 있는 숫자 데이터의 상대적인 차이 때문에 머신러닝 결과가 달라질 수 있다!
  • 숫자 데이터의 상대적인 크기 차이를 제거해야한다!
  • 표준화(standardization)
    • -> 정규분포 z-score가 있다. 추후에 알아보도록 하고
    • -> Min-Max-Scaling -> 이녀석을 먼저 알아보자!
  • 표준화는 정규분포를 기준으로 계산이 되어 이상치에 둔감해 진다!
  • 하지만 표준화는 0과 1사이로 범위가 정해지지 않아 컬럼마다 추이
  • MinMaxScaler는 다음과 같은 식을 가진다
import numpy as np
import pandas as pd
import seaborn as sn


df = pd.read_csv('./data/auto-mpg.csv', header =None) # header = None은 컬럼명이 없다를 명시

df.columns = ['mpg', 'cylinders','displacement','horsepower',
              'weight', 'acceleration', 'year', 'origin', 'name']
# display(df)

df['horsepower'].replace('?',np.nan, inplace=True)       # Missing Value 변화
df.dropna(subset=['horsepower'], axis=0, inplace=True)   # Missing Value 삭제
df['horsepower']= df['horsepower'].astype('float')        # 실수로 데이터 타입 변환            
# display(df.head(3))

df['horsepower']= (df['horsepower']- df['horsepower'].min())/(df['horsepower'].max()- df['horsepower'].min())
df['weight']= (df['weight']- df['weight'].min())/(df['weight'].max()- df['weight'].min())
display(df)

좋은 웹페이지 즐겨찾기