[중급] 가볍게 이것저것
[도서] 추천 시스템 구축, ,데이터가 너무 '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)