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을 제데로 할려면 뭐가 필요한가?
- 데이터의 양
- 양질의 데이터가 들어가 있어야 함
- 데이터의 품질이 중요
- Missing value(결측치)
- Outlier(이상치)
- 중복데이터(의미 있는 중복인지 쓸모없는 중복인지 판단하여 해결)
- Data의 단위처리
- 정규화
- 집의가치 1억~5억
- 집의 연식 1년~40년
- 수치가 1억~5억이 더커서 포커스가 여기에 맞춰짐
=> 이런 데이터들의 처리를 해줘야한다!
예제를 이용해서 전처리를 해보자!
titanic dataset을 이용할 것이다!
- Seaborn module을 사용하!
- 그래프를 그리는 모듈이다
- matplotlib확장버전이라 생각하면 됨
- 이거를 활용하여 titanic dataset을 이용할 것이다.
데이터 전처리 과정
- Missing Value(결치값)
- DataFrame안에 누락된 값이 존재
- 데이터 입력시 실수로 누락됬거나, 파일 변환시 처리 문제로 누락된 경우
-> 결치값은 NaN으로 표현- 이런 Missing Value가 많으면 좋지 않음!
-> 그렇기 때문에 처리를 해야한다
- 삭제 : 만약 데이터가 충분히 많다면 그리고 missing value가 전체의 3~4%이내 일 때
- 대체 : 평균, 중위, 최대, 최소, 빈도값으로 대체할 수 있다.
- 머신러닝 기법으로 이 값을 예측해서 채운다!
- 항상 사용은 불가하고 조건이 있다!
- 이상치 처리
- 이상치를 찾아서 수정
- 이부분은 나중에 다시 알아보도록 하겠다. 지금은 결측치 처리에 집중하자.
- 중복 처리
- duplicated( )
- drop_duplicates( )
- 이 두가지를 통해 처리 할 수 있다.
- 자료형 변환
- 만약 숫자가 문자열(pandas object)로 저장되어 있으면 숫자형으로 범주를 나눠서 카테고리별로 나눠 분류해준다!
이제 예제를 통해 좀 더 알아보도록 하자 일단 anaconda를 통해 seaborn 모듈을 설치해 주도록 하자
conda install seaborn
- 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])
이상치의 경우 나중에 알아보도록 했으니 이번엔 중복 처리를 해보자
- 중복처리
# 의미가 있는 중복인지 아니면 그냥 중복된 데이터가 존재하는지를 판단 # 만약 의미없는 중복된 데이터가 있으면 제거! 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 # 이거 또한 위에서 비교하면서 결과를 출력해준다!
- 데이터 타입의 변환
# 사용하는 데이터 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
범주형 데이터 처리
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
- 정규화 ( 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)
Author And Source
이 문제에 관하여(Data_preprocessing), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@yuyoungjae/Datapreprocessing저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)