본문 바로가기

멀티캠퍼스 프로젝트형 AI 서비스 개발 5회차/ML

3/18 금

728x90

불금! 😻

 

DataFrame이 제공하는 분석용 함수들로 기술 분석(Descriptive Analysis)에 필요한 평균, 표준편차, 분산, 공분산, 상관계수, 사분위 구함

 

1. 집계 함수를 이용할 때 axis를 지정하지 않으면 default는 0, 행 방향. 열끼리 더함. dropna=True가 default이므로 연산에서 제외

import numpy as np
import pandas as pd

data = np.array([[2, np.nan], # np.nan 결치값
               [7, -3],
               [np.nan, np.nan],
               [1, -2]])
# print(data) 
df = pd.DataFrame(data,
                 columns=['one', 'two'],
                 index=['a', 'b', 'c', 'd'])
display(df)
print(df.sum())        # 열끼리 더함. axis=0, dropna=True가 default
print(df.sum(axis=1))  # 행끼리 더함
print(df['two'].sum()) # Series 연산 가능

 

데이터 분석에는 많은 양, 양질의 데이터가 선결되어야 함
Missing Value(결측치), Outlier(이상치), 중복 데이터, Data의 단위 처리, 정규화를 어떻게 처리하는가!

 

데이터 입력 시 실수 혹은 파일 변환 시 처리 문제로 누락되어 Missing Value(결측치. NaN)가 존재할 수 있음

← 삭제 : 데이터가 충분히 많고(rows는 일반적으로 10만 개. 100만 개 이상) NaN이 3~4% 이내
 대체 : ML 기법으로 평균, 중윗값, 최대/최솟값, 빈도를 예측해서 채움. 항상 사용할 수 있는 건 아니고 조건이 있음

 

2. Data의 시각화를 위해 Pandas의 내장된 그래프 도구를 사용하는 것보다 matplotlib를 쓰는 것이 통상적. matplotlib의 확장된 버전이 seaborn module(library). alias는 sns

conda activate machine
conda install seaborn

seaborn으로 캐글 타이타닉 예제 불러와서 데이터 전처리를 해주자

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

df = sns.load_dataset('titanic')              # seaborn으로 간단하게 Titanic dataset 불러오기

display(df)
print(df.info())

print(df['deck'].value_counts(dropna=False)) # dropna=False 옵션으로 NaN 포함. 결치값 확인!
df.isnull().sum(axis=0)                      # NaN인지 확인(mask)해서 갯수 구하기

# for col in df.columns:                      # for문으로 컬럼이 뭐가 있는지 확인
#     print(col)
    
# for col in df.columns:                      # for문으로 각 컬럼의 unique한 값이 뭐가 있는지 확인
#     missing_value = df[col].value_counts()
#     print(missing_value)
    
# missing_df = df.isnull()
# for col in missing_df.columns:
#     missing_value = missing_df[col].value_counts()
#     try:
#         print(col, ' :', missing_value[True]) # NaN이 있는 경우
#     except:
#         print(col, ' :', 0)
        
# df2 = df.drop('deck', axis=1, inplace=False) # Ver.1 결치값(deck column)을 삭제해보자
# display(df2.head())

# thresh_df = df.dropna(axis=1, thresh=500) # Ver.2 column 중에 thresh(NaN) 옵션으로 지정한 수 이상일 때 해당 열을 삭제
# display(thresh_df.head())

# 행을 지우자. subset 옵션으로 열 지정, axis=행(age 컬럼의 NaN 행), how=모두
result_df = df.dropna(subset=['age'], axis=0, how='any')
print(result_df.shape) # (714, 15). 원래는 (891, 15)
print(result_df.info())

 

3. NaN 확인해서 삭제하기 : drop(열 지정) or dropna(thresh 지정)

mean_age = df['age'].mean() # age feature의 NaN을 평균으로 채워주기
# print(mean_age)
df['age'].fillna(mean_age, inplace=True) # 원본 age feature의 NaN을 바꾸기
display(df.head(10))
df['age'].isnull().sum(axis=0)

 

4. NaN 확인해서 대체하기 : fillna()

# 탑승지는 빈도를 이용해서 값을 대체하자. 데이터 특성 상 이웃한 데이터와 유사성을 가질 확률이 높음
df['embarked'].fillna(method='ffill', inplace=True) # 앞의 값으로 NaN을 채워라
# df['embarked'].fillna(method='bfill', inplace=True) # 뒤의 값으로 NaN을 채워라
display(df['embarked'][820:831])
df['embarked'].isnull().sum(axis=0)

 

5. Outlier(이상치)

데이터에 대한 도메인 전문가가 있어야 어떤 데이터를 이상치로 간주할 수 있음. 이상치를 정상 데이터로 치환

 

 

6. 중복 처리

의미 있는 중복인지 혹은 그냥 중복된 것인지 판단해서 후자면 제거하기

df = pd.DataFrame({'c1':['a', 'a', 'b', 'a', 'b'], # 중복 처리
                  'c2':[1,1,1,2,2],
                  'c3':[1,1,2,2,2]})
display(df)
# duplicated() Mask 만듦. Series. 앞에 나온 것과 중복이 되지 않으면 False, 같으면 True
dup_df = df.duplicated()
print(dup_df)
print(df['c2'].duplicated()) # 컬럼에 대한 중복값 확인

df2 = df.drop_duplicates() # 모든 컬럼을 다 비교해서 중복값 삭제
display(df2)

# 특정 컬럼만 비교해서 중복값 삭제. subset 옵션으로 비교할 컬럼들 지정
df3 = df.drop_duplicates(subset=['c2', 'c3'])
display(df3)

 

7. 데이터 타입의 변환

만약 숫자가 문자열(Pandas Object)로 저장되어 있으면, 숫자형으로 변환하여 범주(category)로 구분해주기

import numpy as np
import pandas as pd

df = pd.read_csv('./data/auto-mpg.csv', header=None)

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

display(df.head(3))
# print(df.dtypes) # dtype 확인

# df['horsepower'] = df['horsepower'].astype('float') # Error! 숫자로 바뀔 수 없는 값임
# '?'가 값으로 들어가 있음! 원래 NaN으로 표현하는데 가끔 다른 문자(?, -)로 표현함
print(df['horsepower'].unique())

df['horsepower'].replace('?', np.nan, inplace=True) # '?'를 'nan'으로 대체
print(df['horsepower'].unique())

df.dropna(subset=['horsepower'], axis=0, inplace=True)
print(df['horsepower'].unique())

df['horsepower'] = df['horsepower'].astype('float')
print(df.dtypes)

# replace() 안에 딕셔너리를 넣어서 여러 값을 지정할 수 있음. Object(문자열)
df['origin'].replace({1:'USA',
                     2:'EU',
                     3:'JPN'},
                    inplace=True)
display(df.head())
print(df.dtypes)
df['origin'] = df['origin'].astype('category') # Object를 Category로 변환
print(df.dtypes)

 

8. 구간 분할 : 코드로 연속적인 데이터를 일정한 구간(bin)으로 경계 나누기. 범주형(category) 데이터 처리

df = pd.read_csv('./data/auto-mpg.csv', header=None)

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

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)); print(df.dtypes)

# histogram()로 경계값 알아내기. 뒤에 리스트가 경계값
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)
display(df.head(10))

# get_dummies(). 저출력 아니예요=0, 보통출력이에요=1, 고출력이에요=0
horsepower_dummy = pd.get_dummies(df['hp_bin'])
display(horsepower_dummy.head(10))

One-hot-encoding : 범주형 데이터는 컴퓨터가 인식할 수 없기에 머신러닝 알고리즘에서 바로 사용할 수 없음
→ dummy variable(더미 변수). get_dummies() 이진법(0과 1)으로 표현할 수 있는지 확인

 

9. 정규화(normalization)

DataFrame의 각 열이 가지고 있는 숫자 데이터의 상대적인 차이 때문에 머신러닝 결과가 달라질 수 있음
→ 숫자 데이터의 상대적인 크기 차이를 제거해야 함. 데이터에 따라 표준화/Min-Max Scaling 씀

1. 표준화(Standardization) : 정규분포. Z-score

2. Min-Max Scaling : Xscaled로 숫자 데이터를 0~1 사이로 만듦. 이상치가 존재하면 정규화 효과가 떨어짐

df = pd.read_csv('./data/auto-mpg.csv', header=None)

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

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')     # 실수로 데이터 타입 변환

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.head(3))

 

1. 3/15 화 2. 3/16 수 3. 3/17 목 4. 3/18 금 5. 3/21 월
ML
환경 설정
(아나콘다, 주피터 노트북),
Pandas,
Numpy,
ndarray
ML
Numpy,
행렬곱연산,
전치행렬,
iterator,
axis,
Pandas,
Series,
DataFrame
ML
Pandas,
DataFrame,
함수들
ML
Pandas
데이터 분석,
데이터 전처리
ML
Pandas,
데이터 시각화

* 배운 것을 잘 정리해놓고 복습하자!

728x90

'멀티캠퍼스 프로젝트형 AI 서비스 개발 5회차 > ML' 카테고리의 다른 글

3/22 화  (0) 2022.03.22
3/21 월  (0) 2022.03.21
3/17 목  (0) 2022.03.17
3/16 수  (0) 2022.03.16
3/15 화  (0) 2022.03.15