본문 바로가기
자격증/빅데이터 분석기사 (실기)

02_데이터 탐색과 데이터 정제

by 이민우 2022. 5. 30.
728x90
반응형

 

출처 : https://book.naver.com/bookdb/book_detail.nhn?bid=21488029 

 

공개적 빅데이터분석기사 실기

본 도서는 한국데이터산업진흥원에서 실시하는 빅데이터분석기사 국가기술자격 실기시험 대비 도서입니다.본 교재는 PYTHON을 활용하여 쉽고 빠른 자격증 취득으로 이어질 수 있도록 도움을 줄

book.naver.com

*해당 글은 학습을 목적으로 위의 도서 내용 중 일부 내용만을 요약하여 작성한 포스팅입니다.

 상세 내용 및 전체 내용 확인을 원하신다면 도서 구매를 추천드립니다.


 

 

데이터는 다음 데이터 사용

https://www.kaggle.com/code/lottoexpecter/python-5-data-search-data-preprocessing/data?select=Ex_CEOSalary.csv 

https://www.kaggle.com/code/lottoexpecter/python-5-data-search-data-preprocessing/data?select=Ex_Missing.csv 

 

 

단변량 데이터 탐색

  • csv 파일에서의 데이터는 다음과 같은 방식으로 Pandas의 데이터프레임으로 불러올 수 있다.
  • info() 함수 사용 시 대략적인 정보를 확인할 수 있다.
import pandas as pd

data = pd.read_csv("/Ex_CEOSalary.csv", encoding="utf-8");
data.info()

  • 범주형 자료는 value_counts() 함수를 사용해 범주별 빈도수를 확인할 수 있다.
data['industry'].value_counts()

  • 범주형 자료가 숫자로 되어있어 확인하기 어렵다면 아래와 같은 방식으로 문자로 변경이 가능하다.
data['industry'] = data['industry'].replace([1, 2, 3, 4], ['Service', 'IT', 'Finance', 'Others'])
data['industry'].value_counts()

  • 또한 범주형의 경우 막대 그래프, 파이 그래프 등을 사용하면 쉽게 빈도수를 비교할 수 있다.
%matplotlib inline
data['industry'].value_counts().plot(kind='pie') # bar 등의 값을 파라미터로 넣을 수도 있다.

  • 연속형 자료의 경우 describe() 함수를 이용하면 요약 통계량을 일목요연하게 확인할 수 있다.
data.describe()

  • describe() 함수 사용시 평균과 중위수를 한 번에 확인할 수 있다.
  • 이 때 주의해야 할 점은 평균과 중위수차이가 일치하면 이상치가 적은 데이터이고, 차이가 크면 이상치가 많은 데이터이므로 주의가 필요하다는 점이다.
  • 자료의 분포를 더 명확히 보고 싶다면 왜도(skewness)와 첨도(kurtosis)를 확인하여 정규분포와의 유사성을 확인하는 것이 좋다.
  • 왜도0일수록 정규분포와 일치하며, 음수면 이상치가 작은 값들이고 양수면 이상치가 큰 값들이다.
data.skew()
  • 첨도 역시 0이면 정규분포의 높이와 동일하다.
data.kurtosis()
  • 또한 범주형 자료를 확인할 때 막대 그래프와 파이 그래프 등을 사용했다면, 연속형 자료는 히스토그램을 사용하면 자료의 형태를 명확히 파악할 수 있다.
import matplotlib.pyplot as plt

data.hist(bins=50, figsize=(20, 15)) # bins : 구간 너비 / figsize = 도표 크기

  • 위의 결과를 보면 다수의 이상치가 존재함을 알 수 있다. 이상치는 제거, 변환 등의 방법을 통해 관리할 수 있다.

 

 

 

 

이변량 데이터 탐색

  • 데이터 탐색은 단일 변수 뿐 아니라 두 변수 간의 탐색도 필요하다.
  • 특히 회귀의 경우 선형성 여부를 판단하는 과정이 필요하다.
  • 두 변수간 상관관계는 cors() 함수를 통해 파악할 수 있다.
  • 이 때 파라미터인 method에는 pearson, spearman, kendall이 사용 가능하며, 피어슨이 기본값으로 입력된다.
data.corr() # method 파라미터로 pearson, spearman, kendall 지정 가능 ( pearson이 DEFAUL )

  • 두 연속형 변수 간 상관 관계는 산점도를 이용하여 확인하는 것이 좋다.
plt.scatter(data['sales'], data['salary'], alpha=0.5)
plt.show()

  • groupby 함수를 사용하면 두 변수를 하나의 그룹으로 묶어 확인할 수 있다.
data.groupby('industry')[['salary']].describe()

 

 

 

이상치 처리

  • 이상치는 분석 전 반드시 해결해야 할 데이터이다.
  • 정상적인 범위 밖에 있는 너무 크거나 작은 값을 일컫는다.
  • 이상치는 전체 분석 결과에 큰 영향을 줄 수 있다.
  • 이상치를 시각적으로 확인하기 위해 상자수염도표가 주로 사용된다.
data.boxplot(column='salary', return_type='both')

  • 또한 이상치 처리의 대표적인 방법으로는 IQR 방식이 있다.
  • IQR 방식은 (제1사분위수 - 1.5*IQR) < X < (제3사분위수 + 1.5 * IQR) 범위 외의 수를 이상치로 판단하는 방법이다.
  • 파이썬에서 코드로 구현은 아래와 같이 수행할 수 있다.
Q1_sal = data['salary'].quantile(q=0.25)
Q3_sal = data['salary'].quantile(q=0.75)
IQR_sal = Q3_sal - Q1_sal

data_IQR = data[(data['salary'] < Q3_sal+IQR_sal*1.5) & 
                (data['salary'] > Q1_sal-IQR_sal*1.5)]

data_IQR['salary'].hist()

  • 이렇게 제거된 데이터에 corr() 함수를 사용해 선형관계를 파악하면 아래와 같이 개선됨을 확인할 수 있다.
data_IQR.corr()

  • 이상치는 위와같이 제거할 수도 있지만, 굳이 제거를 하는 것이 아니라 변환을 하는 방법도 존재한다.
  • 변환의 대표적인 방법으로는 log 변환, 제곱근 변환 방법이 있다.
  • 로그 변환은 아래와 같이 수행할 수 있다.
import numpy as np

data['log_salary'] = np.log(data['salary'])
data['log_sale'] = np.log(data['sales'])
data['log_roe'] = np.log(data['roe'])

data.corr()

  • 다음으로 제곱근 변환은 아래와 같이 수행할 수 있다.
data['sqrt_salary'] = np.sqrt(data['salary'])
data['sqrt_sale'] = np.sqrt(data['sales'])
data['sqrt_roe'] = np.sqrt(data['roe'])

data.corr()

  • 위와 같은 방식으로 이상치를 제거하지 않고 변환을 함으로써 전체 데이터에 대한 이상치의 영향력을 줄일 수 있다.
  • 다만 이 방식은 이상치를 제거하는 방식보다 현실적인 활동도에 제약이 많다.

 

 

 

결측치

  • 결측치는 데이터가 어떠한 이유로 없는 것이다.
  • 판다스에서의 결측치는 NaN으로 표현되며, isnull(), notnull() 함수로 확인할 수 있다.
  • isnull()은 결측이면 True, notnull()은 결측이 아니면 True를 반환한다.
  • 두 함수 모두 sum() 함수와 결합하여 각각 결측치의 수와 정상값의 수를 확인할 수 있다.
import pandas as pd

data = pd.read_csv('/Ex_Missing.csv', encoding='utf-8')
data.isnull().sum()

  • 전체가 아닌 행 단위로 결측값의 개수를 구할 수 있다.
  • 행의 경우 sum() 함수에 파라미터로 1을 입력하면 된다.
data.isnull().sum(1)

  • 결측값의 제거는 dropna()가 사용된다.
  • 결측값 제거는 행 제거, 열 제거, 특정 행 또는 열 제거 방법이 있다.
  • 가장 먼저 행을 제거하는 방법은 아래와 같이 dropna() 메소드의 파라미터로 axis=0을 주면 된다.
data['missing'] = data.isnull().sum(1)
data.head(10)

  • 열을 제거하는 방법은 axis=1을 파라미터로 주면 된다.
data_del_col = data.dropna(axis = 1)
data_del_col.head(10)

  • 만약 전체 행/열 이 아닌 특정 행/열 을 제거하고 싶다면 아래와 같이 사용할 수 있다.
  • 만약 [[ ]] 안에 모든 칼럼명들을 넣는다면 dropna를 그냥 사용하는 것과 같다.
data_del_col = data[['salary']].dropna(axis=0)
data_del_col.head()

  • 결측치가 많은 데이터라면 제거만이 능사가 아니다.
  • 이럴 때는 변환의 방법이 필요하다.
  • 변환은 특정 값으로, 평균 등으로, 다른 변수 값으로, 그리고 그룹 평균으로 대체하는 방법 등이 사용된다.
  • 변환은 fillna() 함수가 사용되며, 특정 값으로 대체하는 방법은 아래와 같다.
data_fill_zero = data.fillna(0)
data_fill_zero.isnull().sum()

  • 결측치는 바로 앞의 값 혹은 바로 뒤의 값으로 변환이 가능하다.
  • 바로 앞의 값은 fillna() 함수에 파라미터로 method='ffill' 혹은 'pad'를 주면 된다.
data_fill_before = data.fillna(method='ffill')
data_fill_before.head(10)

  • 바로 뒤의 값을 사용하는 방법은 fillna 함수의 method 파라미터에 'bfill' 혹은 'backfill'을 주는 것이다.
data_fill_after = data.fillna(method='bfill')
data_fill_after.head(10)

  • 평균으로 대체하는 방법은 다음과 같다.
  • 비단 평균 뿐 아니라 최대/최소/중위값 등도 사용 가능하다.
df_fill_mean = data.fillna(data.mean())
# df_fill_mean = data.where(pd.notnull(data), data.mean(), axis='columns')
# median(중위수), max(최대), min(최소) 값도 사용 가능

df_fill_mean.head(10)

  • 만약 자신의 변수가 아닌 특정 칼럼의 평균등으로 모든 결측치를 변환하고 싶다면 아래와 같은 방법을 사용할 수 있다.
df_fill_mean_sal = data.fillna(data.mean()['salary'])

df_fill_mean_sal.head(10)

  • 집단 평균값으로의 대체 방법은 아래와 같다.
fill_mean_func = lambda g : g.fillna(g.mean())
data_group_mean = data.groupby('industry').apply(fill_mean_func)

data_group_mean.head(10)

  • 추가로 집단 평균 값이 아닌 분석자가 자체적으로 설정한 특정 값으로 대체하고 싶다면 아래와 같이 사용할 수 있다.
  • 코드는 산업을 기준으로 1은 1000, 2는 2000으로 결측치를 대체한다는 것이다.
fill_values = {1 : 1000, 2: 2000}
fill_func = lambda d : d.fillna(fill_values[d.name])

data_group_custom = data.groupby('industry').apply(fill_func)
data_group_custom.head(10)

  • 혹은 각 칼럼별로 별도의 방법을 적용할 수도 있다.
missing_fill_val = { 'salary' : data.salary.interpolate(), #보간법
                     'sales' : data.sales.mean() , #평균
                     'roe' : 'missing' #문자열로 대체
                    }

data_multi = data.fillna(missing_fill_val)
data_multi.head(10)

 

728x90
반응형

'자격증 > 빅데이터 분석기사 (실기)' 카테고리의 다른 글

03_02. 회귀  (0) 2022.06.04
03_01. 분류  (0) 2022.05.30
03_머신러닝 프로세스  (0) 2022.05.30
02_01. 데이터 정제 실전 과제  (0) 2022.05.30
01. 파이썬 기초  (0) 2022.05.27