728x90
반응형

👉이전글에서 소개된 것처럼 AI 모델은 많은 데이터를 기반으로 생성됩니다.
그렇기때문에 양질의 데이터는 높은 퀄리티의 AI 모델을 생성하기 위해 반드시 필요한 요소죠.

본 글에서는 일반적인 데이터를 AI 모델에 활용할 양질의 데이터로 가공하기 위한 방법들을 다뤄보겠습니다.

사용 환경은 아래와 같습니다.

  • IDE : Jupyter Notebook
  • Language : python
  • library : pandas

데이터 탐색

  • 샘플데이터 : ratings.csv
  1. 데이터 확인
# 라이브러리 불러오기
import pandas as pd

# 샘플데이터 가져오기
df = pd.read_csv("./data/ratings.csv")

# 앞에서부터 데이터확인
df.head() # 앞 10개 (default)
df.head(5) # 앞 5개

# 뒤에서부터 데이터확인
df.tail() # 뒤 10개 (default)
df.tail(5) # 뒤 5개
  1. 데이터프레임 정보 확인
    : 데이터 컬럼정보 확인
df.info()

## 결과
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 100836 entries, 0 to 100835
# Data columns (total 4 columns):
#  #   Column     Non-Null Count   Dtype  
# ---  ------     --------------   -----  
#  0   userId     100836 non-null  int64  
#  1   movieId    100836 non-null  int64  
#  2   rating     100836 non-null  float64
#  3   timestamp  100836 non-null  object 
# dtypes: float64(1), int64(2), object(1)
# memory usage: 3.1+ MB
  1. 통계적 특성 확인
    : 데이터의 row수와 평균, 최소/최대값 등을 확인
df.describe()

#     userId    movieId    rating
# count    100836.000000    100836.000000    100836.000000
# mean    326.127564    19435.295718    3.501557
# std    182.618491    35530.987199    1.042529
# min    1.000000    1.000000    0.500000
# 25%    177.000000    1199.000000    3.000000
# 50%    325.000000    2991.000000    3.500000
# 75%    477.000000    8122.000000    4.000000
# max    610.000000    193609.000000    5.000000



데이터 결합과 정렬

  • 샘플데이터 : movies.csv, links.csv, ratings.csv, users.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df_movies = pd.read_csv("./data/movies.csv")
df_links = pd.read_csv("./data/links.csv")
df_ratings = pd.read_csv("./data/ratings.csv")
df_users = pd.read_csv("./data/users.csv")
  1. 데이터 붙이기 : concat()
# 단순 위/아래로 row를 붙임
df_concat_1 = pd.concat([df_movies, df_ratings])

# 옆으로 row를 붙임
df_concat_2 = pd.concat([df_movies, df_ratings], axis=1)

# 합치는 두 데이터프레임에 모두 존재하는 row의 인덱스만 가져옴
df_concat_3 = pd.concat([df_movies, df_ratings], join='inner')
  1. 데이터 병합하기 : merge()
# on='key값'이 없을 경우, default 설정대로 같은 이름을 가진 열이 자동으로 key값으로 지정됨
pd.merge(df_movies, df_ratings)

# movieId 기준 병합
pd.merge(df_movies, df_ratings, on='movieId')

# join 방법 설정
pd.merge(df_movies, df_ratings, how='outer' on='movieId') # outer join
pd.merge(df_movies, df_ratings, how='left' on='movieId') # left outer join
pd.merge(df_movies, df_ratings, how='right' on='movieId') # right outer join
  1. 정렬하기 : sort_values()
# movieId기준 오름차순 정렬
df.sort_values(by='movieId')

# movieId기준 내림차순 정렬
df.sort_values(by='movieId', ascending=False)

# movieId기준 오름차순 정렬 후 바로 적용
df.sort_values(by='movieId', inplace=True)

# 정렬로 인해 뒤섞인 인덱스를 재배열
df.reset_index()
df.reset_index(drop=True, inplace=True) # 기존 인덱스 삭제 후, 재배열된 인덱스 적용



데이터 필터링과 편집

  • 샘플데이터 : preprocessing_03.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/preprocessing_03.csv")
  1. 데이터 필터링
# 성별의 구성을 확인합니다. 
df['gender'].value_counts()

# 성별이 남자인지를 확인해 봅니다.
df['gender']=='M'

# 전체 데이터프레임에서 성별이 남자인 사람으로 필터링한 정보를 가져옵니다.
df[df['gender']=='M']

# 전체 데이터프레임에서 'userId'가 5인 고객이 본 영화 목록을 확인합니다.
df[df['userId']==5]
len(df[df['userId']==5])

# 전체 데이터프레임에서 'userId'가 5인 고객이 평점 2점 이하를 준 영화 목록을 확인합니다.
df[(df['userId']==5) & (df['rating']<=2) ]

# 필터링 결과 중 'title'만 출력
df[(df['userId']==5) & (df['rating']<=2)]['title']
  1. 컬럼명 변경
# 기존 컬럼명 확인하기
df.columns

# 새로운 컬럼명 List를 작성하여 대체하기
df.columns = ['movieId', 'imdbId', 'tmdbId', '영화제목', 'genres', 'userId', 'rating',
       'timestamp', 'gender', 'age', 'occupation', 'zipcode']

# 기존 컬럼명 선택하여 변경 ( df.rename(columns={'기존 컬럼명' : '새 컬럼명'}) )
df = df.rename(columns={'zipcode':'우편번호'})
  1. 컬럼 생성
# 컬럼 생성 후 기본값 세팅 ( df['새로운 컬럼명'] = 기본값 )
df['new'] = 0

# df['영화제목']의 정보를 문자열 처리한 후 괄호'(',')'를 제외한 4자리의 숫자만 가져온 후에 새로운 컬럼 'year'에 세팅
df['year'] = df['영화제목'].str[-5:-1]

# 데이터 분리 후 새로운 컬럼 생성
df['genres'].str.split('|')    # 배열 형태
df['genres'].str.split('|', expand=True).head() # 'expand=True' 옵션을 통해 새로운 데이터프레임으로 생성
  1. 컬럼 삭제
# new 컬럼 삭제
df.drop(columns=['new'])
df.drop(columns=['new'], inplace=True) # 변경내용 적용

# 필요한 컬럼만 선택하여 다시 저장
new_columns = ['movieId', 'imdbId', 'tmdbId', '영화제목', 'year', 'genres', 'userId', 'rating', 'timestamp', 'gender', 'age', 'occupation', '우편번호']
df = df[new_columns]



데이터 결측치 처리

  • 샘플데이터 : preprocessing_04.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/preprocessing_04.csv")
  1. 결측치 확인
# 결측치 행 확인 ( 결측치가 있을 경우 True를 반환 )
df.isnull()

# 각 열별 결측치 갯수 확인
df.isnull().sum()
  1. 결측치 제거
# 결측치가 있는 행 모두 삭제
df_temp = df.dropna()

# 결측치가 있는 열 모두 삭제
df_temp2 = df.dropna(axis=1)

# 행 전체가 결측치인 행만 모두 삭제
df_temp3 = df.dropna(how ='all')

# 행의 결측치가 n초과인 행만 모두 삭제
df_temp4 = df.dropna(thresh=n)

# 특정 열 중 결측치가 있는 경우의 행만 모두 삭제
df_temp5 = df.dropna(subset=['MovieId'])
df.dropna(subset=['MovieId'], inplace=True) # 데이터프레임에 바로 적용
  1. 결측치 채우기
# 결측치를 단일 값(0)으로 대체
df.fillna(0)

# 특정 열의 결측치만 0으로 대체하기
df_na_sample2['UserId'].fillna(0, inplace=True) # 데이터프레임에 바로 적용

# 특정 열의 결측치만 평균값으로 대체하기
df['Age'].fillna(df_na_sample2['Age'].mean(), inplace=True)

# 특정 열의 결측치만 최빈값으로 대체하기
df['Gender'].fillna(df_na_sample2['Gender'].mode()[0], inplace=True)

# 결측치 이전값으로 채우기
df.fillna(method='ffill')

# 결측치 이후값으로 채우기
df.fillna(method='bfill')



데이터 타입 변환/중복데이터 제거

  • 샘플데이터 : preprocessing_05.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/preprocessing_05.csv")
  1. 데이터 타입 확인
# 모든 컬럼의 데이터타입을 확인
df.dtypes

# 컬럼별 데이터타입 확인
df['MovieId'].dtype
  1. 데이터 타입 변경
# 모든 Columns의 데이터 타입을 'object' 형으로 변경
df_temp = df.astype('object')

# 특정 컬럼의 데이터 타입을 변경
df = df.astype({'Year':'int'})
  1. 중복데이터 처리
# 중복 데이터 확인 ( 첫 번째 값은 False, 두 번째 값부터는 True 반환 )
df.duplicated()

# 데이터프레임 df의 'Title'과 'UserId' 컬럼이 중복이 되는 데이터를 확인
df[df.duplicated(['Title','UserId'])]

# 예제 : 영화 제목이 같은 영화를 두번 본 고객이 존재한다고?!
df[(df['Title']=='Iron Man') & (df['UserId']==550)]
df[df.duplicated(['Title','UserId'])]

# 중복데이터 제거
df.drop_duplicates(['Title','UserId', 'Year'], ignore_index=True)    # 기존 인덱스를 무시하고 새로 인덱스를 부여



데이터 이상치 처리

  • 샘플데이터 : preprocessing_06.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/preprocessing_06.csv")
  1. 이상치 탐지
# 컬럼별 통계적 특성 확인
df.describe()

# 시각화를 통한 이상치 탐지
# 라이브러리 불러오기 
import matplotlib.pyplot as plt

# 차트 영역 설정하기 ( box plot 차트 )
plt.figure()
plt.boxplot(df['Age'], labels=['Age'])
plt.show()

  1. 이상치 확인
# IQR의 1.5배 이상 크거나 작은 데이터를 이상치로 판별
# IQR 계산
# 중앙값 계산
Q2 = df['Age'].median()

# 하위 25%, 상위 25% 범위 계산
Q1 = df['Age'].quantile(0.25)
Q3 = df['Age'].quantile(0.75)
IQR = Q3 - Q1

# 이상치 판별
df['IsOutlier_Age'] = (df['Age'] < Q1 - 1.5 * IQR) | (df['Age'] > Q3 + 1.5 * IQR)
  1. 이상치 처리
# 위에서 생성한 이상치여부 컬럼(IsOutlier_Age) 활용하여 이상치 삭제
df = df[df['IsOutlier_Age'] == False]

# 이상치 대체
df.loc[df['IsOutlier_Age'], 'Age'] = df['Age'].median() # 중앙값 대체



데이터 인코딩

  • 샘플데이터 : preprocessing_07.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/preprocessing_07.csv")
  1. 레이블 인코딩
    : 범주형 데이터를 숫자로 변환하는 방법으로, 각 범주에 고유한 숫자를 할당하는 방식입니다.
    예를 들어, "남성", "여성"과 같은 범주형 데이터를 각각 0과 1로 변환하는 방법이 있습니다.
# 라이브러리 불러오기
from sklearn.preprocessing import LabelEncoder

# Label Encoder 호출하기
le = LabelEncoder()

# 'Occupation' 컬럼의 데이터를 Label 인코딩하기.
le_occupation = le.fit_transform(df['Occupation'])
df_le['Occupation_Le'] = le_occupation
df_le['Occupation_Le']
# array([ 0, 20,  1, ..., 11, 11,  7])

# label Encoding 매핑 클래스 확인
le.classes_
# array(['K-12 student', 'academic/educator', 'artist', 'clerical/admin',
#        'college/grad student', 'customer service', 'doctor/health care',
#        'executive/managerial', 'farmer', 'homemaker', 'lawyer', 'other',
#        'programmer', 'retired', 'sales/marketing', 'scientist',
#        'self-employed', 'technician/engineer', 'tradesman/craftsman',
#        'unemployed', 'writer'], dtype=object)

# Pandas의 map() 함수를 사용하여 레이블 인코딩
# 'Occupation' 컬럼의 값들을 lable mapping
label_mapping = { "other" : 0 , 
                  "academic/educator" : 1, 
                  "artist" : 2, 
                  "clerical/admin" : 3, 
                  "college/grad student" : 4, 
                  "customer service" : 5, 
                  "doctor/health care" : 6, 
                  "executive/managerial" : 7, 
                  "farmer" : 8, 
                  "homemaker" : 9, 
                  "K-12 student" : 10,
                  "lawyer" : 11, 
                  "programmer" : 12, 
                  "retired" : 13, 
                  "sales/marketing" : 14, 
                  "scientist" : 15, 
                  "self-employed" : 16, 
                  "technician/engineer" : 17, 
                  "tradesman/craftsman" : 18, 
                  "unemployed" : 19, 
                  "writer" : 20 }

# pandas replace() 메소드를 사용해서 값을 대체
df_le['Occupation_Map'] = df['Occupation'].map(label_mapping)
  1. 더미 변수 생성
    : 각 카테고리를 이진 형태로 표현하는 방법
    각각의 값을 고유한 이진 벡터로 변환하여 해당하는 값의 위치에 1을 표시하고, 나머지 위치에는 0을 표시합니다. (원-핫 인코딩)
# | 구분자 기준으로 데이터를 분할하여 생성된 list type 데이터를 다시 저장
df['Genres'] = df['Genres'].str.split('|')

# list type으로 저장된 데이터를 모두 나누어 새로운 row로 생성
df = df.explode('Genres')

# get_dummies() 함수를 사용 더미변수 생성
pd.get_dummies(df, columns=['Genres'])
pd.get_dummies(df['Genres'])
pd.get_dummies(df['Genres'], prefix='Genre_')    # 더미변수 컬럼의 prefix 설정
pd.get_dummies(df['Genres'], drop_first=True)    # 더미변수 첫번째 컬럼 삭제
df = pd.get_dummies(df, columns=['Genres'], prefix='Genre', drop_first=True)    # 최종

# 더미변수 컬럼 외의 컬럼들을 키값으로 그룹화하여 중복데이터 제거
# 'groupby()'는 특정 컬럼의 값을 기준으로 데이터프레임을 그룹화하여 그룹별로 연산을 수행할 수 있습니다.
# 'agg()'는 그룹화된 데이터프레임에 대해 다양한 집계 함수들을 적용하여 그룹 별로 연산 결과를 집계한 결과를 반환합니다.
df = df.groupby(['MovieId', 'ImdbId', 'TmdbId', 'Title', 'Year', 'UserId', 'Rating', 'Gender', 'Age', 'Occupation']).agg('sum').reset_index()



데이터 스케일링

  • 샘플데이터 : preprocessing_08.csv
  1. 데이터 불러오기
# 라이브러리 불러오기
import pandas as pd

df = pd.read_csv("./data/preprocessing_08.csv")
  1. 데이터 정규화
    : 데이터를 일정 범위로 변환하는 스케일링 방법으로, 데이터를 0과 1 사이의 값으로 변환하는 것을 의미
    정규화는 다양한 스케일을 가진 변수들을 동일한 범위로 맞춰줌으로써, 변수 간의 크기 차이를 제거하여 모델이 각 변수를 공평하게 처리할 수 있도록 돕습니다.
# 라이브러리 불러오기
from sklearn.preprocessing import MinMaxScaler

# MinMaxScaler 호출하기
min_max_scaler = MinMaxScaler()

# 'Age', 'Rating' 컬럼의 데이터를 Min Max Scaling 하기
df_normalized = min_max_scaler.fit_transform(df[['Age', 'Rating']])
  1. 데이터 표준화
    : 데이터를 평균이 0이고 표준편차가 1인 분포로 변환하는 스케일링 방법으로, 데이터를 표준정규분포에 따르는 값으로 변환하는 것을 의미
    표준화는 데이터의 분포를 중심으로 조절하여 이상치에 덜 민감하게 만들어줌으로써, 모델의 안정성을 높이고 예측 결과를 개선하는 데 도움을 줍니다.
# 라이브러리 불러오기
from sklearn.preprocessing import StandardScaler

# StandardScaler 호출하기
standard_scaler = StandardScaler()

# 'Age', 'Rating' 컬럼의 데이터를 StandardScaling 하기
df_standardized = standard_scaler.fit_transform(df[['Age', 'Rating']])



이어서

다음은 전처리된 데이터를 이용하여 AI 모델링을 진행하는 과정을 살펴보겠습니다.

반응형

'개발 > AI' 카테고리의 다른 글

[AI] pandas/sklearn을 활용한 머신러닝 모델링  (0) 2024.04.12
KT AI 해커톤 회고 (2)  (1) 2023.11.02
KT AI 해커톤 회고 (1)  (0) 2023.10.27
[AI] Softmax Regression  (0) 2023.10.01
[NLP] Embedding  (0) 2023.09.23

+ Recent posts