파이썬/Data Science

[Data Science] 데이터 퀄리티 높이기

취준생코린이 2021. 6. 18. 10:52
728x90

데이터 퀄리티의 중요성

분석할때 아무리 좋은 알고리즘을 써도 안좋은 데이터를 분석하면 안 좋은 결과가 나온다.

예를 들어 연매출을 비교하여 식당을 차리려는데

a지역의 연매출은 40, 50, 20, 80, 1300000

b지역 연매출 390, 450, 990, 840, 570으로

평균은 a가 260038, b가 648로 a의 연매출 평균이 더 높아보이지만 알고보니 다른데이터들은 만원단위인데 

1300000는 일원 단위여서 b지역이 더 좋은 지역이지만 a를 선택하는 결론이 날수있다.

 

이처럼 수백 수천 가지의 데이터들중 하나라도 잘못된 데이터가 있으면 예상치 못한 결과가 나오거나 오류가 발생할수있다.

 

좋은 데이터의 기준

  1. 완결성
  2. 유일성
  3. 통일성
  4. 정확성

 

1. 완결성 (Completeness): "필수적인 데이터는 모두 기록되어 있어야 한다"라는 의미

예를들어 회원가입을 할때 아이디, 비번, 이름, 나이등은 필수항목이고 전화번호, 주소등은 선택항목일때

데이터 셋에 필수항목이 비어있으면 완결성에 위배되었고 선택항목은 비어있어도 위배되지 않았다.

 

 

데이터의 완결성은 어떻게 알 수 있을까?

결측값(채워져야 하는데 비어있는 값)이 있는지 확인하면된다.

DataFrame에서 결측값은 NaN(Not a Number)으로 표시된다.

 

2. 유일성(Uniqueness): 동일한 데이터가 불필요하게 중복되어 있으면 안된다.

유일성이 중요한 이유: 어떤 데이터를 수정할 건데 동일한 데이터가 2개 이상있으면 하나만 수정되고 다른데이터들은 수정하는 걸 까먹을 수 있다.

 

3. 통일성(Conformity):  데이터가 동일한 형식을 저장되어 있어야 한다.

여기서 형식은 데이터 타입, 단위, 포맷등 다양한 걸 의미한다.

날짜 표기법이 다르거나  띄어쓰기의 유무가 다르거나 여러가지의 통일성 위배가 있다.

 

4. 정확성(Accuracy): 데이터가 정확해야 한다.

부정확한 데이터는 분석에 혼란을 일으킬 수 있다.

보통 정확성은 데이터를 모을때 발생한다.

데이터가 정확한지 확인하는 방법은 이상점(Outlier)확인하기같은 방법이 있다.


데이터 클리닝

import pandas as pd
%matplotlib inline

 

1. 데이터 클리닝 : 완결성

  • 결측값이 없는게 제일 좋다
  • 결측값이 자주 발생한다면 원인을 파악해야한다.
df = pd.read_csv("attendance.csv", index_col=0)
df

결측값이 있으므로 데이터가 완결성이 없다.

 

데이터에서 결측값 찾기

.isnull()
결측값은 True, 결측값이 아닌 값은 False 반환

 

# isnull(): 결측값은 True, 결측값이 아닌 값은 False를 반환해줘서 결측값을 찾아주는 함수
df.isnull()

 

isnull()로 결측값들을 찾아내고 sum()으로 결측값들이 컬럼에 얼마나 있는지 확인했다.

배구 컬럼에 결측에 결측치가 3개인걸 확인할수있다.

# 어느 컬럼에 결측값이 얼마나 있는지 확인하기
df.isnull().sum()

결측값이 있을때 해결방법 - 삭제

.dropna()
결측값이있는 레이블 삭제

 

결측값 해결의 가장 좋은 방법은 재조사 해서 결측값을 채우는것이다.

하지만 재조사하여 결측값을 채우는게 불가능 할경우 해결방법

  • 첫번째: 그냥 그대로 두기, 어쩔때는 결측값이 있다는게 또 나름대로의 의미가 있을 수 있다. 이럴경우에는 결측값이 있다는 걸 미리 고려해야한다.
  • 두번째: 결측값이있는 레이블을 삭제. ".dropna()"사용

이때 값이 바로 저장되는게 아니므로 원본값을 변경하려면 아래방식대로 해야한다

df=df.dropna() # 또는
df.dropna(inplace=True)
# 결측값이 있는 모든 레이블 삭제
df.dropna()

 

 

# 결측값이 있는 모든 컬럼 삭제
df.dropna(axis='columns')

 

결측값이 있을때 해결방법 - 채우기

.fillna(대체할값)
결측값을 다른 값들로 대체

결측값을 채워기

  • fillna : 결측값을 다른 값들로 대체해주는 함수
  • 보통 평균값이나 중간값을 이용한다 이때 값이 바로 저장되는게 아니므로 원본값을 변경하려면 아래방식대로 해야한다
 df=df.fillna(대체할값) # 또는
df.fillna(대체할 값, inplace=True)

 

결측값들을 평균으로 대체해보기

df.mean()
# 결측값을 모두 평균값으로 대체
df.fillna(df.mean())
# 원본에 저장하려면 inplace=True 사용
df.fillna(df.median(), inplace=True)
df

 

 

실습과제 1

스팀게임 데이터 정리하기

스팀(Steam)은 온라인 게임을 유통하는 플랫폼입니다.
스팀 플랫폼에서 가장 반응이 좋은 게임이 무엇인지 알아보려고 하는데요.

데이터를 살펴보니 결측값이 있는 것 같네요. 분석에 앞서 결측값을 제거해 봅시다.

결측값이 있는 모든 row를 삭제해주세요.

 

steam = pd.read_csv('steam_1.csv')
steam.dropna(axis='index', inplace=True)

 

2. 데이터 클리닝 : 유일성

.drop_duplicates()
컬럼 값들이 중복인 행을 삭제

drop_duplicates사용

  • 컬럼 값들이 중복인 행을 삭제하는 함수다. 즉, 행이름이 달라도 내용이 중복이면 삭제된다
  • subset=None이 디폴트이고 특정 컬럼값만 비교하여 삭제하고 싶으면 subset에 컬럼을 적으면 된다.
df.drop_duplicates(subset = 'col1')
  • 원본값에 저장 하고 싶으면 inplace=True 속성을 사용
  • 행이 아닌 열을 삭제하고 싶으면 .T로 전치해주면 된다.

 

dust = pd.read_csv('dust.csv', index_col=0)
dust.head()

# 각각의 인덱스가 몇개인지 횟수를 구해보자.
# 07월 31일만 2개인것을 확인할수 있다.
dust.index.value_counts()

 

중복인 행 삭제

# 중목된 행(row)삭제
dust.drop_duplicates(inplace=True)

 

중복인 컬럼 삭제

컬럼삭제는 주의해야 될게 전치함수인 T를 써서 전치해줘서 중복된 컬럼을 인덱스로 바꿔준후 삭제하고

다시 전치해줘서 원래 데이터프레임 형태로 돌려줘야한다.

.drop_duplicates() 함수가 행만 삭제하기 때문이다.

그리고 여기서는 inplace=True를 사용하지 못한다.

# 중복된 컬럼 삭제
dust.T # 데이터 전치 / 행과 열을 바꿈
# 여기서는 inplace=True을 사용할수없다, 다시 
dust = dust.T.drop_duplicates().T

 

3. 데이터 클리닝 : 정확성

이상점(Outlier)

  • 다른 값들과 너무 동떨어져있는 데이터

이상점을 판단하는 기준 사분위수 이용

  • 1사분위수 : 25% 지점(Q1)
  • 2사분위수 : 50% 지점(Q2)
  • 3사분위수 : 75% 지점(Q3)
  • 사분위 범위(IQR): Q3 - Q1
  • 이상점 범위: Q1 - 1.5IQR보다 작거나, Q3 + 1.5IQR보다 크면 이상점이다
  • 이 기준은 절대적인 기준이 아니라 box플롯에서 저기준으로 이상점을 설정한다

이상점은 제거하거나 의미있는 이상점이면 그것또한 고려해서 데이터분석을 하면 된다.

 

 

다음은 맥주 데이터에서 알콜도수를 box플롯으로 그려서 이상점이 있는지 확인한거다.

beer = pd.read_csv('beer.csv', index_col=0)

# abv(알콜도수) 컬럼 box플롯 그리기
beer.plot(kind="box", y="abv")

 

기술통계에서 보여주는 값들로 아까위에서 설명한 이상점 범위를 구할수있다.

# abv 컬럼 기술통계
beer['abv'].describe()

 

 

.quantile(숫자)

.quantile(숫자)을 이용해서 특정지점의 값을 알수있다. 즉, 1사분위인 25%범위의 값을 가져오고 싶으면

quantile(0.25)하몀 된다.   

# abv 컬럼 특정지점
q1 = beer['abv'].quantile(0.25)
q3 = beer['abv'].quantile(0.75)
# IQR
iqr = q3-q1

# 이상점 구하기
# Q1 - 1.5IQR보다 작거나, Q3 + 1.5IQR보다 크면 condision변수에 저장, 즉 이상점들만 가져오기
condision = (beer['abv']<q1-1.5*iqr) | (beer['abv']>q3+1.5*iqr)
beer[condision]

abv가 이상점인 행들

위에서 2250인덱스의 abv컬럼을 보면 5.5인데 도수가 0.055인데 5.5로 잘못입력한거 같다. 따라서 도수를 0.055로 고쳐주자

beer.loc[2250, 'abv'] = 0.055

 

나머지 두 인덱스들은 스타일을 보니 맥주가 아닌 것들이 잘못 들어왔으므로 삭제해주자.

이제 다시 이상점을 구하면 2250인덱스는 사라졌을거다. 다시 이상점을 구하고 이상점들의 인덱스를 가져와서 drop함수로 삭제해주면 된다.

condision = (beer['abv']<q1-1.5*iqr) | (beer['abv']>q3+1.5*iqr)
# 이상점이 있는 인덱스보기
beer[condision].index
# 이상점이 있는 인덱스 지우기
beer.drop(beer[condision].index, inplace=True)

 

이제 다시 abv컬럼의 box플롯을 그리면 이상점이 없다.

beer.plot(kind='box', y="abv")

 

3. 데이터 클리닝: 정확성 2

관계적 이상점(Relational Outlier)

  • 두변수의 관계를 고려했을 때 이상한 데이터

 

 

읽기 점수와 쓰기점수 컬럼의 관계를 산점도로 그려봤다.

exam = pd.read_csv('exam_outlier.csv')
exam.plot(kind="scatter", x='reading score', y='writing score')

 

위에 그래프를 보면 혼자 엄청 떨어진 값이 보일거다.

이상점때문에 상관관계도 적게 나온 것을 확인할 수 있다.

exam.corr()

 

쓰기 점수가 100점 이상인 이상점을 삭제하기위해 이상점 출력

exam[exam['writing score'] > 100]

이상점이 51번행에 있다

 

이상점이있는 51번행 삭제하고 삭제후 다시 산점도를 그려봤다

exam.drop(51, inplace=True)
exam.plot(kind="scatter", x='reading score', y='writing score')

이제 아까보다 많이 보기 좋아졌지만 쓰기 점수는 90점이상인데 읽기점수가 40점미만인 값이 혼자 동떨어져있다.

이값이 관계적 이상점이다. 이값도 삭제해주자.

condition = (exam['writing score']>90) & (exam['reading score']<40)
exam[condition]

# 위의 관계적 이상점 삭제
exam.drop(373, inplace=True)
exam.plot(kind="scatter", x='reading score', y='writing score')

관계적 이상점 삭제후

 

이제 다시 상관계수를 구해보면 상관계수가 많이 오른것을 볼수있다.

exam.corr()

 

 

실습과제 2

영화 평점 분석하기 1

영화 감독이 꿈인 래진이는 영화에 대한 데이터 분석을 해보려고 합니다.

movie_metadata.csv에는 영화에 대한 제목, 감독, 배우, 평점, 예산 등의 정보가 있는데요.

과연 예산을 많이 쓰면 소비자 평점이 높아질 지 궁금합니다.

산점도를 그려봤더니, 아주 큰 예산을 쓴 영화 몇 개 때문에 상관 관계를 파악할 수가 없네요.

너무 예산이 큰 일부 영화를 제거하고, 다시 분석해봐야 할 것 같습니다.

예산을 기준으로 75% 지점에서 5 IQR 만큼 더한 것보다 큰 예산의 영화는 제거하고, 다시 산점도를 그려보세요.

 

movie = pd.read_csv('movie_metadata.csv')
movie.head()
movie.plot(kind='scatter', x='budget', y='imdb_score')

# 이상점을 확인하기 위해 box플롯을 그려보자.
# budget에서 이상점들이 있는것을 확인할수 있다.
movie.plot(kind='box')

budget에만 이상점 존재

 

# budget 컬럼 이상점 삭제하기
q1 = movie['budget'].quantile(0.25)
q3 = movie['budget'].quantile(0.75)
iqr = q3-q1
condision = movie['budget']>q3+5*iqr
movie.drop(movie[condision].index, inplace=True)
movie['budget'].plot(kind='box')

 

movie.plot(kind='scatter', x='budget', y='imdb_score')

 

영화 평점 분석하기 2

이번에도 예산이 너무 큰 영화 몇 개를 제거해보려고 합니다.

하지만 이번에는 IQR이 아니라 예산 상위 15개를 제거하려고 하는데요.

movie_metadata.csv에서 예산이 가장 높은 15개 영화를 제거하고, 산점도를 그려보세요.

movie = pd.read_csv('movie_metadata.csv')
# budget 컬럼 결측치 제거
movie.drop(movie[movie['budget'].isnull()].index, axis=0, inplace=True)
# 예산 상위 15개 영화 제거
budgetDrop = movie.sort_values(by='budget', ascending=False).head(15)
movie.drop(budgetDrop.index, inplace=True)
movie.plot(kind='scatter', x='budget', y='imdb_score')

 

728x90