[중급] 가볍게 이것저것

[도서] 추천 시스템 구축, ,데이터가 너무 'big' 해서 생기는 문제 해결법?

PassionPython 2019. 8. 19. 17:04

해결방안

import pandas as pd
books = pd.read_csv('data/books.csv')
ratings = pd.read_csv('data/ratings.csv')
C:\Users\one\AppData\Local\Continuum\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3057: DtypeWarning: Columns (3) have mixed types. Specify dtype option on import or set low_memory=False.
  interactivity=interactivity, compiler=compiler, result=result)

유저가 몇 번 별점을 매겼는지, 도서가 몇 번 별점이 매겨졌는지를 확인

import numpy as np
user_count = ratings.groupby('userID').agg({'bookRating' : [np.size, np.mean, np.std]})
book_count = ratings.groupby('ISBN').agg({'bookRating' : [np.size, np.mean, np.std]})
# 50% 지점에도 값이 1 이라는 것은, 반 이상의 사람이 딱 한 번만 참여했다는 의미.
# 그런데 평균이 10 이라는 것은, 많이 한 사람들이 평균을 끌어올렸음을 의미.
# 그 근거로 표준편차인 std 가 90 이나 되는 수치를 보이고 있다.

user_count[('bookRating', 'size')].describe()
count    105283.000000
mean         10.920851
std          90.562825
min           1.000000
25%           1.000000
50%           1.000000
75%           4.000000
max       13602.000000
Name: (bookRating, size), dtype: float64
# 50% 지점에도 값이 1 이라는 것은, 반 이상의 도서가 딱 한 번만 언급됨을 의미
# 75% 지점의 값이 2 이므로, 75%의 도서가 두 번 이하로 언급됨을 의미
# 그런데 평균이 3 이라는 것은, 많이 평가받은 도서들이 평균을 조금 끌어올렸음을 의미.
# 사람만큼은 아니지만, 그 근거로 표준편차인 std 가 12 임을 보이고 있다.

book_count[('bookRating', 'size')].describe()
count    340556.000000
mean          3.376185
std          12.436252
min           1.000000
25%           1.000000
50%           1.000000
75%           2.000000
max        2502.000000
Name: (bookRating, size), dtype: float64
# 유저 참여 빈도가 편향되어있음을 히스토그램으로 확인

%matplotlib inline
user_count.hist(('bookRating', 'size'), bins=50)
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x00000217010EA668>]],
      dtype=object)

# 도서가 평가된 횟수가 편향되어있음을(인기도) 히스토그램으로 확인

%matplotlib inline
book_count.hist(('bookRating', 'size'), bins=50)
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x000002170123FB00>]],
      dtype=object)

# 최소 2회 이상 참여한 인원만 고려하기 위한 코드
# 헤비라고 이름 붙이고, 불리언인덱싱으로 뽑아옵니다.

user_count.loc[user_count[('bookRating', 'size')] > 2, 'heavy'] = 1
user_count_filtered = user_count[user_count['heavy'] == 1]
# heavy 컬럼의 std 가 0 인 것은, 1 밖에 없으므로 편차가 존재하지 않아서 입니다.
user_count_filtered.describe()
  bookRating heavy
  size mean std  
count 33615.000000 33615.000000 33615.000000 33615.0
mean 31.700431 3.927866 3.167336 1.0
std 158.283188 2.310885 1.413517 0.0
min 3.000000 0.000000 0.000000 1.0
25% 4.000000 2.250000 2.511224 1.0
50% 7.000000 3.764706 3.533979 1.0
75% 16.000000 5.500000 4.111540 1.0
max 13602.000000 10.000000 5.773503 1.0
# 최소 2회 이상 평가된 도서만 고려하기 위한 코드
# 헤비라고 이름 붙이고, 불리언인덱싱으로 뽑아옵니다.

book_count.loc[book_count[('bookRating', 'size')] > 2, 'heavy'] = 1
book_count_filtered = book_count[book_count['heavy'] == 1]
# heavy 컬럼의 std 가 0 인 것은, 1 밖에 없으므로 편차가 존재하지 않아서 입니다.
book_count_filtered.describe()
  bookRating heavy
  size mean std  
count 83847.000000 83847.000000 83847.000000 83847.0
mean 9.939616 2.655413 3.200658 1.0
std 23.884803 1.932984 1.694266 0.0
min 3.000000 0.000000 0.000000 1.0
25% 3.000000 1.333333 2.581989 1.0
50% 5.000000 2.500000 3.746999 1.0
75% 8.000000 3.750000 4.358899 1.0
max 2502.000000 10.000000 5.773503 1.0
# isin() 을 사용하여 사용자가 heavy-user 인 경우만 골라내고, 책도 동일하게 진행합니다.

ratings = ratings.loc[ratings['userID'].isin(user_count_filtered.index)]
books = books.loc[books['ISBN'].isin(book_count_filtered.index)]
# 도서 정보에서 정작 필요한 부분은 ISBN 코드와 도서명 두 개뿐이므로
# 해당 컬럼들만 선택하여 저장.

books_column = ['ISBN', 'bookTitle']
books = books[books_column]

ratings.to_csv('data/filtered_ratings.csv', index=False)
books.to_csv('data/filtered_books.csv', index=False)