Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
Tags
- 만화 영화
- 제임스 클리어
- 습관
- QGIS
- 가족
- 커피
- 빅데이터 분석기사 필기
- pandas
- 이기적 출판사
- 로맨스
- 아주 작은 습관의 힘
- 진심
- 애니메이션
- 완결
- 사랑
- 넷플릭스
- 네이버 웹툰
- 제주도
- 빅데이터 분석기사
- 서귀포
- python
- 이범선
- 산책
- 액션
- 네이버 완결 웹툰
- 웹툰
- 네이버
- geopandas
- 완결 웹툰
- 영화
Archives
- Today
- Total
JuJuKwakKwak
[3] 사용한 코드 : 망고플레이트 사이트 크롤링, CBF 추천시스템 본문
Data Science/여행 종합 추천 시스템 : 이지트립
[3] 사용한 코드 : 망고플레이트 사이트 크롤링, CBF 추천시스템
jujukwakkwak 2022. 5. 27. 18:411개씩 크롤링¶
In [1]:
# 필요한 라이브러리를 임포트하기
import sys # 시스템
import os # 시스템
# 데이터 다루기
import pandas as pd
import numpy as np
# selenium 크롤링
from selenium import webdriver
from selenium.webdriver import ActionChains as AC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
# 크롬 드라이버
import chromedriver_autoinstaller
# beautifulsoup 크롤링
import requests
from bs4 import BeautifulSoup
# lxml 크롤링
import lxml.html
# 시간 조절
import time
# 시간 측정
from tqdm import notebook
# 정규표현식
import re
# 경고 무시
import warnings
warnings.filterwarnings('ignore')
In [2]:
# 지역 키워드를 입력하기
keyword = '부산'
# page 정하기
page = 1
In [3]:
# 크롬창 띄우기
chrome_path = chromedriver_autoinstaller.install()
driver = webdriver.Chrome(chrome_path)
driver.maximize_window() # 창 최대화
# 키워드가 입력된 망고플레이트 사이트에 들어가기
driver.get(" https://www.mangoplate.com/search/{0}?keyword={0}&page={1}".format(keyword, page))
time.sleep(2)
In [ ]:
# 광고창 없애기
# 광고창 iframe 접근하기
driver.switch_to.frame("google_ads_iframe_/395211568/init/desktop_all_0")
# '다시 보지 않기' 버튼 클릭하기
element = '#ad > div > button.ad_btn.ad_block_btn'
driver.find_element_by_css_selector(element).click()
# # 방법1
# element = '#ad > div > button.ad_btn.ad_block_btn'
# driver.find_element_by_css_selector(element).click()
# # 방법2
# element = '/html/body/div[2]/div/div/button[1]'
# driver.find_element_by_xpath(element).click()
# # 방법3
# element = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#ad > div > button.ad_btn.ad_block_btn')))
# element.click()
# # 방법4
# from selenium.webdriver.common.keys import Keys
# element=driver.find_element_by_partial_link_text("다시")
# element.send_keys(Keys.ENTER)
In [ ]:
# # 방법5
# # 열려 있는 세션 개수 확인
# popup_count = len(driver.window_handles)
# i = popup_count
# # 팝업창 제거
# while i > 0:
# if i == 1:
# driver.switch_to.window(driver.window_handles[i-1])
# i = 0
# break
# else:
# driver.switch_to.window(driver.window_handles[i-1])
# driver.close()
# i -= 1
# # 현재 열려 있는 세션 확인
# print(driver.window_handles)
In [14]:
# 첫 번째 음식점 클릭
element = 'body > main > article > div.column-wrapper > div > div > section > div.search-list-restaurants-inner-wrap > ul > li:nth-child(4) > div:nth-child(1) > figure > a > div > img'
driver.find_element_by_css_selector(element).click()
In [15]:
# 가게 이름 크롤링
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.restaurant_title_wrap > span > h1'
title_raw = driver.find_element_by_css_selector(element)
title = title_raw.text
print(title, type(title))
포르타나 <class 'str'>
In [16]:
# 가게 전체 평점 점수 크롤링
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.restaurant_title_wrap > span > strong > span'
total_raw = driver.find_element_by_css_selector(element)
total = total_raw.text
print(total, type(total))
4.5 <class 'str'>
In [17]:
# 조회수 크롤링
try:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status.branch_none > span.cnt.hit'
view_raw = driver.find_element_by_css_selector(element)
view = view_raw.text
except:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status > span.cnt.hit'
view_raw = driver.find_element_by_css_selector(element)
view = view_raw.text
print(view, type(view))
25,499 <class 'str'>
In [19]:
# 리뷰 개수 크롤링
try:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status.branch_none > span.cnt.review'
review_raw = driver.find_element_by_css_selector(element)
num_review = review_raw.text
except:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status > span.cnt.review'
review_raw = driver.find_element_by_css_selector(element)
num_review = review_raw.text
print(num_review, type(num_review))
13 <class 'str'>
In [22]:
# 별표 개수 크롤링
try:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status.branch_none > span.cnt.favorite'
star_raw = driver.find_element_by_css_selector(element)
num_star = star_raw.text
except:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status > span.cnt.favorite'
star_raw = driver.find_element_by_css_selector(element)
num_star = star_raw.text
print(num_star, type(num_star))
608 <class 'str'>
In [23]:
# 음식 종류 및 메뉴 크롤링
element1 = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > table > tbody > tr:nth-child(3) > td > span'
type_raw = driver.find_element_by_css_selector(element1)
type_raw = type_raw.text
food_type = type_raw
try:
element2 = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > table > tbody > tr:nth-child(9) > td > ul'
menu_raw = driver.find_element_by_css_selector(element2)
food_menu = menu_raw.text
food_type = [type_raw, food_menu]
except:
pass
print(food_type)
['기타 양식', '마르게리따\n6,300원\n후라이드치킨\n5500원원']
In [20]:
# 데이터 프레임 만들기
a = {'Title' : title,
'Point' : total,
'View' : view,
'Review' : num_review,
'Star' : num_star,
'Type' : food_type}
df = pd.DataFrame.from_dict(a, orient='index')
df = df.transpose()
df.head()
Out[20]:
Title | Point | Review | Star | Type | |
---|---|---|---|---|---|
0 | 비비비당 | 136,524 | 74 | 3,780 | [카페 / 디저트, 오늘의 차\n10,000원\n우전녹차\n10,000원\n특말차\... |
for 문으로 크롤링 : 1페이지만¶
In [1]:
# 필요한 라이브러리를 임포트하기
import sys # 시스템
import os # 시스템
# 데이터 다루기
import pandas as pd
import numpy as np
# selenium 크롤링
from selenium import webdriver
from selenium.webdriver import ActionChains as AC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
# 크롬 드라이버
import chromedriver_autoinstaller
# beautifulsoup 크롤링
import requests
from bs4 import BeautifulSoup
# lxml 크롤링
import lxml.html
# 시간 조절
import time
# 시간 측정
from tqdm import notebook
# 정규표현식
import re
# 경고 무시
import warnings
warnings.filterwarnings('ignore')
In [2]:
# 지역 키워드를 입력하기
keyword = '부산'
# page 정하기
page = 1
In [3]:
# 크롬창 띄우기
chrome_path = chromedriver_autoinstaller.install()
driver = webdriver.Chrome(chrome_path)
driver.maximize_window() # 창 최대화
# 키워드가 입력된 망고플레이트 사이트에 들어가기
driver.get(" https://www.mangoplate.com/search/{0}?keyword={0}&page={1}".format(keyword, page))
time.sleep(2)
# 광고창 iframe 접근하기
driver.switch_to.frame("google_ads_iframe_/395211568/init/desktop_all_0")
# '다시 보지 않기' 버튼 클릭하기
element = '#ad > div > button.ad_btn.ad_block_btn'
driver.find_element_by_css_selector(element).click()
In [4]:
# 음식점 1개에서 정보 크롤링 함수
def FoodCrawling(row, col):
# 전체 담을 그릇
total_dict = {}
k = 0
for i in range(row):
driver.execute_script("window.scrollTo(0, 200)")
for j in range(col):
# 동영상 1개 담을 그릇
sub_dict = {}
# 음식점 클릭
element = f'body > main > article > div.column-wrapper > div > div > section > div.search-list-restaurants-inner-wrap > ul > li:nth-child({i+1}) > div:nth-child({j+1}) > figure > a > div > img'
driver.find_element_by_css_selector(element).click()
time.sleep(0.5)
# 가게 이름 크롤링
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.restaurant_title_wrap > span > h1'
title_raw = driver.find_element_by_css_selector(element)
title = title_raw.text
# 가게 전체 평점 점수 크롤링
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.restaurant_title_wrap > span > strong > span'
total_raw = driver.find_element_by_css_selector(element)
total = total_raw.text
# 조회수 크롤링
try:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status.branch_none > span.cnt.hit'
view_raw = driver.find_element_by_css_selector(element)
view = view_raw.text
except:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status > span.cnt.hit'
view_raw = driver.find_element_by_css_selector(element)
view = view_raw.text
# 리뷰 개수 크롤링
try:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status.branch_none > span.cnt.review'
review_raw = driver.find_element_by_css_selector(element)
num_review = review_raw.text
except:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status > span.cnt.review'
review_raw = driver.find_element_by_css_selector(element)
num_review = review_raw.text
# 별표 개수 크롤링
try:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status.branch_none > span.cnt.favorite'
star_raw = driver.find_element_by_css_selector(element)
num_star = star_raw.text
except:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status > span.cnt.favorite'
star_raw = driver.find_element_by_css_selector(element)
num_star = star_raw.text
# 음식 종류 및 메뉴 크롤링
element1 = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > table > tbody > tr:nth-child(3) > td > span'
type_raw = driver.find_element_by_css_selector(element1)
type_raw = type_raw.text
food_type = type_raw
try:
element2 = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > table > tbody > tr:nth-child(9) > td > ul'
menu_raw = driver.find_element_by_css_selector(element2)
food_menu = menu_raw.text
food_type = [type_raw, food_menu]
except:
pass
# sub_dict에 담기
sub_dict['title'] = title
sub_dict['Point'] = total
sub_dict['View'] = view
sub_dict['Review'] = num_review
sub_dict['Star'] = num_star
sub_dict['Type'] = food_type
# total_dict에 담기
total_dict[k] = sub_dict
k += 1
time.sleep(1)
# 뒤로 가기
driver.back()
time.sleep(0.5)
df = pd.DataFrame.from_dict(total_dict, orient='index')
driver.close()
return df
In [5]:
df = FoodCrawling(row=10, col=2)
df
Out[5]:
title | Point | View | Review | Star | Type | |
---|---|---|---|---|---|---|
0 | 비비비당 | 4.6 | 136,567 | 74 | 3,782 | [카페 / 디저트, 오늘의 차\n10,000원\n우전녹차\n10,000원\n특말차\... |
1 | 톤쇼우 | 4.6 | 26,166 | 38 | 867 | 까스 요리 |
2 | 해목 | 4.5 | 324,671 | 157 | 5,477 | [정통 일식 / 일반 일식, 특히츠마부시 (민물장어덮밥)\n55,000원\n특카이센... |
3 | 신발원 | 4.5 | 259,872 | 166 | 5,903 | 딤섬 / 만두 |
4 | 할매국밥 | 4.5 | 128,987 | 88 | 2,812 | 탕 / 찌개 / 전골 |
5 | 라호짬뽕 | 4.5 | 22,480 | 11 | 516 | 정통 중식 / 일반 중식 |
6 | 포르타나 | 4.5 | 25,500 | 13 | 608 | [기타 양식, 마르게리따\n6,300원\n후라이드치킨\n5500원원] |
7 | 이재모피자 | 4.4 | 161,823 | 220 | 4,079 | [기타 양식, 이재모치즈크러스트피자 (S)\n24,000원\n이재모치즈크러스트피자 ... |
8 | 마가만두 | 4.4 | 112,477 | 97 | 2,930 | 정통 중식 / 일반 중식 |
9 | 블랙업커피 | 4.4 | 179,876 | 113 | 3,479 | 카페 / 디저트 |
10 | 고옥 | 4.4 | 226,662 | 80 | 4,164 | 돈부리 / 일본 카레 / 벤토 |
11 | 나가하마만게츠 | 4.4 | 64,018 | 52 | 1,874 | [라멘 / 소바 / 우동, 나가하마라멘\n8,000원\n야끼라멘\n8,500원\n오... |
12 | 평산옥 | 4.4 | 68,020 | 44 | 1,740 | 국수 / 면 요리 |
13 | 칸다소바 | 4.4 | 61,735 | 48 | 1,340 | [라멘 / 소바 / 우동, 마제소바\n9,500원\n아부라소바\n9,500원\n돼지... |
14 | 동백섬횟집 | 4.4 | 80,253 | 22 | 1,641 | 해산물 요리 |
15 | 모티 | 4.4 | 19,329 | 11 | 487 | 칵테일 / 와인 |
16 | 아리아 | 4.4 | 701 | 4 | 7 | 뷔페 |
17 | 해운대소문난암소갈비집 | 4.3 | 234,667 | 181 | 4,894 | 고기 요리 |
18 | 금수복국 | 4.3 | 110,956 | 154 | 2,710 | 해산물 요리 |
19 | 거대갈비 | 4.3 | 76,598 | 30 | 1,084 | 고기 요리 |
for 문으로 크롤링 : 10페이지까지¶
In [1]:
# 필요한 라이브러리를 임포트하기
import sys # 시스템
import os # 시스템
# 데이터 다루기
import pandas as pd
import numpy as np
# selenium 크롤링
from selenium import webdriver
from selenium.webdriver import ActionChains as AC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
# 크롬 드라이버
import chromedriver_autoinstaller
# beautifulsoup 크롤링
import requests
from bs4 import BeautifulSoup
# lxml 크롤링
import lxml.html
# 시간 조절
import time
# 시간 측정
from tqdm import notebook
# 정규표현식
import re
# 경고 무시
import warnings
warnings.filterwarnings('ignore')
In [12]:
# 음식점 1개에서 정보 크롤링 함수
def FoodCrawling(row, col):
# 전체 담을 그릇
total_dict = {}
k = 0
for i in range(row):
driver.execute_script("window.scrollTo(0, 400)")
for j in range(col):
# 동영상 1개 담을 그릇
sub_dict = {}
# 음식점 클릭
element = f'body > main > article > div.column-wrapper > div > div > section > div.search-list-restaurants-inner-wrap > ul > li:nth-child({i+1}) > div:nth-child({j+1}) > figure > a > div > img'
driver.find_element_by_css_selector(element).click()
time.sleep(0.5)
# 가게 이름 크롤링
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.restaurant_title_wrap > span > h1'
title_raw = driver.find_element_by_css_selector(element)
title = title_raw.text
# 가게 전체 평점 점수 크롤링
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.restaurant_title_wrap > span > strong > span'
total_raw = driver.find_element_by_css_selector(element)
total = total_raw.text
# 조회수 크롤링
try:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status.branch_none > span.cnt.hit'
view_raw = driver.find_element_by_css_selector(element)
view = view_raw.text
except:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status > span.cnt.hit'
view_raw = driver.find_element_by_css_selector(element)
view = view_raw.text
# 리뷰 개수 크롤링
try:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status.branch_none > span.cnt.review'
review_raw = driver.find_element_by_css_selector(element)
num_review = review_raw.text
except:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status > span.cnt.review'
review_raw = driver.find_element_by_css_selector(element)
num_review = review_raw.text
# 별표 개수 크롤링
try:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status.branch_none > span.cnt.favorite'
star_raw = driver.find_element_by_css_selector(element)
num_star = star_raw.text
except:
element = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > header > div.status > span.cnt.favorite'
star_raw = driver.find_element_by_css_selector(element)
num_star = star_raw.text
# 음식 종류 및 메뉴 크롤링
try:
element1 = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > table > tbody > tr:nth-child(3) > td > span'
type_raw = driver.find_element_by_css_selector(element1)
type_raw = type_raw.text
food_type = type_raw
except:
element1 = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > table > tbody > tr:nth-child(2) > td > span'
type_raw = driver.find_element_by_css_selector(element1)
type_raw = type_raw.text
food_type = type_raw
try:
element2 = 'body > main > article > div.column-wrapper > div.column-contents > div > section.restaurant-detail > table > tbody > tr:nth-child(9) > td > ul'
menu_raw = driver.find_element_by_css_selector(element2)
food_menu = menu_raw.text
food_type = [type_raw, food_menu]
except:
pass
# sub_dict에 담기
sub_dict['title'] = title
sub_dict['Point'] = total
sub_dict['View'] = view
sub_dict['Review'] = num_review
sub_dict['Star'] = num_star
sub_dict['Type'] = food_type
# total_dict에 담기
total_dict[k] = sub_dict
k += 1
time.sleep(1)
# 뒤로 가기
driver.back()
time.sleep(0.5)
df = pd.DataFrame.from_dict(total_dict, orient='index')
driver.close()
return df
In [13]:
# 지역 키워드를 입력하기
print('지역 : 강릉, 부산, 제주')
keyword = input('지역을 입력하시오: ')
지역 : 강릉, 부산, 제주 지역을 입력하시오: 부산
In [29]:
# 모든 데이터 프레임 담을 그릇
king_dict = {}
# 1페이지부터 순차적으로 들어가 크롤링하기
pages = 10
for page in range(pages):
# 크롬창 띄우기
chrome_path = chromedriver_autoinstaller.install()
driver = webdriver.Chrome(chrome_path)
driver.maximize_window() # 창 최대화
driver.get(" https://www.mangoplate.com/search/{0}?keyword={0}&page={1}".format(keyword, page+1))
time.sleep(2)
# 광고창 iframe 접근하기
driver.switch_to.frame("google_ads_iframe_/395211568/init/desktop_all_0")
# '다시 보지 않기' 버튼 클릭하기
element = '#ad > div > button.ad_btn.ad_block_btn'
driver.find_element_by_css_selector(element).click()
king_dict[page] = FoodCrawling(row=10, col=2)
time.sleep(0.5)
In [30]:
king_dict
Out[30]:
{6: title Point View Review Star Type 0 초원복국 4.0 15,001 19 326 해산물 요리 1 버거스올마이티 4.0 14,118 18 293 브런치 / 버거 / 샌드위치 2 아저씨대구탕 4.0 21,166 17 515 해산물 요리 3 공원칼국수 4.0 8,046 13 212 국수 / 면 요리 4 광안리막창집 4.0 7,879 13 246 고기 요리 5 공순대 4.0 9,784 12 235 탕 / 찌개 / 전골 6 자매국밥 4.0 16,311 17 389 탕 / 찌개 / 전골 7 스톤스트릿 4.0 10,371 12 163 퓨전 양식 8 종각집 4.0 4,339 7 88 국수 / 면 요리 9 미누식당 4.0 7,013 12 166 닭 / 오리 요리 10 초량1941 3.9 48,327 59 2,060 카페 / 디저트 11 모루비 3.9 57,306 46 2,229 [카페 / 디저트, 파운드 (1구)\n2,500원] 12 웨이브온커피 3.9 27,770 39 1,250 카페 / 디저트 13 해성막창집 3.9 43,106 71 1,657 고기 요리 14 쌍둥이돼지국밥 3.9 104,763 239 3,009 탕 / 찌개 / 전골 15 백화양곱창 3.9 28,766 49 766 고기 요리 16 해운대밀면 3.9 63,326 60 2,020 국수 / 면 요리 17 신창국밥 3.9 46,589 48 939 탕 / 찌개 / 전골 18 손목서가 3.9 19,924 20 530 카페 / 디저트 19 카린 영도 플레이스 3.9 8,188 13 202 카페 / 디저트, 7: title Point View Review Star \ 0 초량845 3.9 36,610 15 405 1 부산족발 3.9 15,147 52 414 2 대정양곱창 3.9 22,197 25 628 3 부산집언양불고기 3.9 28,987 34 324 4 포항돼지국밥 3.9 30,497 35 714 5 해운대원조할매국밥 3.9 25,829 50 1,252 6 이름난기장산곰장어 3.9 48,168 28 1,008 7 에쎄떼 3.9 13,494 10 373 8 어라이크커피 3.9 8,603 8 290 9 보느파티쓰리 3.9 9,292 10 305 10 딤딤섬 3.9 15,026 22 291 11 기장손칼국수 3.9 47,968 52 1,646 12 속씨원한대구탕 3.9 65,990 98 1,967 13 문화공감 수정 3.9 8,379 14 156 14 음주양식당어부 3.9 7,406 9 204 15 네살차이 3.9 18,923 8 686 16 라메르 3.9 4,159 6 29 17 비앤씨 3.9 7,718 24 111 18 라푀유크로와상 3.9 8,808 11 217 19 양자강 3.9 9,048 8 198 Type 0 [퓨전 한식, 아메리카노\n4,500원\n초량제라떼\n7,000원\n릴렉싱 티톡스\... 1 고기 요리 2 탕 / 찌개 / 전골 3 고기 요리 4 탕 / 찌개 / 전골 5 탕 / 찌개 / 전골 6 해산물 요리 7 카페 / 디저트 8 카페 / 디저트 9 카페 / 디저트 10 딤섬 / 만두 11 국수 / 면 요리 12 해산물 요리 13 카페 / 디저트 14 [기타 양식, La Carbonara\n29,000원\nOstriche Concav... 15 [카페 / 디저트, 커피\n5,000원\n카페오레\n5,000원\n레몬키위소다\n6... 16 퓨전 양식 17 베이커리 18 베이커리 19 정통 중식 / 일반 중식 , 8: title Point View Review Star \ 0 부다면옥 3.9 7,520 8 235 1 에테르 3.9 4,713 13 119 2 버거샵 3.9 28,586 27 749 3 마루팥빙수단팥죽 3.9 15,326 18 300 4 초필살돼지구이 3.9 18,699 17 544 5 시골밥상풍원장 3.9 17,624 13 170 6 그릿비 일광 3.9 15,623 11 399 7 쿠루미과자점 3.9 4,313 9 120 8 문토스트 3.9 26,480 16 763 9 바오하우스 3.9 7,775 10 202 10 오후의홍차 3.9 10,783 13 325 11 신가네떡볶이 3.9 5,888 11 98 12 수수하지만굉장해 3.9 4,877 11 146 13 프랭클린커피로스터스 3.9 3,103 17 77 14 사보이 3.9 35,920 14 768 15 메트르아티정 3.9 11,342 11 390 16 바닷마을과자점 3.9 7,854 9 201 17 호랑이젤라떡 3.9 2,338 4 91 18 원조언양불고기 3.9 43,944 13 699 19 오드이븐 3.9 1,308 4 15 Type 0 국수 / 면 요리 1 카페 / 디저트 2 브런치 / 버거 / 샌드위치 3 카페 / 디저트 4 [고기 요리, 뒷고기 (1인분)\n6,500원\n돼지갈비 (1인분)\n9,000원\... 5 한정식 / 백반 / 정통 한식 6 카페 / 디저트 7 카페 / 디저트 8 기타 한식 9 기타 중식 10 카페 / 디저트 11 기타 한식 12 까스 요리 13 카페 / 디저트 14 치킨 / 호프 / 펍 15 베이커리 16 베이커리 17 카페 / 디저트 18 고기 요리 19 카페 / 디저트 , 9: title Point View Review Star Type 0 로우앤스윗 3.9 690 4 30 카페 / 디저트 1 도시농가코페도코 3.9 4,468 9 192 카페 / 디저트 2 카페38.5 3.9 1,405 7 20 카페 / 디저트 3 라이옥 3.9 6,754 11 77 베트남 음식 4 해운대31cm해물칼국수 3.9 12,096 15 311 국수 / 면 요리 5 유일한식탁 3.9 2,452 6 46 까스 요리 6 어바웃제이 3.9 6,251 9 141 카페 / 디저트 7 SANT EUSTACHIO IL CAFE 3.9 3,007 6 23 카페 / 디저트 8 로우앤스윗 3.9 3,015 9 99 카페 / 디저트 9 목구멍 3.9 126 9 2 고기 요리 10 다리집 3.8 57,019 157 1,717 기타 한식 11 뚱보집 3.8 41,578 27 1,277 해산물 요리 12 본전돼지국밥 3.8 58,173 84 1,027 탕 / 찌개 / 전골 13 스시심 3.8 94,359 35 1,535 회 / 스시 14 가내수공업양식당비토 3.8 33,173 42 898 이탈리안 15 모던테이블 3.8 29,192 26 1,025 카페 / 디저트 16 화국반점 3.8 28,661 28 731 정통 중식 / 일반 중식 17 맛찬들왕소금구이 3.8 49,822 62 1,303 고기 요리 18 겐짱카레 3.8 22,457 26 791 돈부리 / 일본 카레 / 벤토 19 파크하얏트라운지 3.8 40,477 18 752 칵테일 / 와인}
In [23]:
# csv 파일로 저장
df1 = king_dict[0]
df2 = king_dict[1]
df3 = king_dict[2]
df4 = king_dict[3]
df5 = king_dict[4]
df6 = king_dict[5]
df7 = king_dict[6]
df8 = king_dict[7]
df9 = king_dict[8]
df10 = king_dict[9]
df1.to_csv('Busan1.csv', encoding='utf-8-sig', index=False)
df2.to_csv('Busan2.csv', encoding='utf-8-sig', index=False)
df3.to_csv('Busan3.csv', encoding='utf-8-sig', index=False)
df4.to_csv('Busan4.csv', encoding='utf-8-sig', index=False)
df5.to_csv('Busan5.csv', encoding='utf-8-sig', index=False)
df6.to_csv('Busan6.csv', encoding='utf-8-sig', index=False)
df7.to_csv('Busan7.csv', encoding='utf-8-sig', index=False)
df8.to_csv('Busan8.csv', encoding='utf-8-sig', index=False)
df9.to_csv('Busan9.csv', encoding='utf-8-sig', index=False)
df10.to_csv('Busan10.csv', encoding='utf-8-sig', index=False)
데이터 정제¶
In [4]:
# 저장한 csv 불러오기
df1 = pd.read_csv('Busan1.csv')
df2 = pd.read_csv('Busan2.csv')
df3 = pd.read_csv('Busan3.csv')
df4 = pd.read_csv('Busan4.csv')
df5 = pd.read_csv('Busan5.csv')
df6 = pd.read_csv('Busan6.csv')
df7 = pd.read_csv('Busan7.csv')
df8 = pd.read_csv('Busan8.csv')
df9 = pd.read_csv('Busan9.csv')
df10 = pd.read_csv('Busan10.csv')
In [5]:
df_list = [df1, df2, df3, df4, df5, df6, df7, df8, df9, df10]
df_all = pd.concat(df_list, ignore_index=True)
df_all
Out[5]:
title | Point | View | Review | Star | Type | |
---|---|---|---|---|---|---|
0 | 비비비당 | 4.6 | 136,578 | 74 | 3,782 | ['카페 / 디저트', '오늘의 차\n10,000원\n우전녹차\n10,000원\n특... |
1 | 톤쇼우 | 4.6 | 26,176 | 38 | 867 | 까스 요리 |
2 | 해목 | 4.5 | 324,680 | 157 | 5,477 | ['정통 일식 / 일반 일식', '특히츠마부시 (민물장어덮밥)\n55,000원\n특... |
3 | 신발원 | 4.5 | 259,881 | 166 | 5,903 | 딤섬 / 만두 |
4 | 할매국밥 | 4.5 | 128,996 | 88 | 2,812 | 탕 / 찌개 / 전골 |
... | ... | ... | ... | ... | ... | ... |
195 | 모던테이블 | 3.8 | 29,192 | 26 | 1,025 | 카페 / 디저트 |
196 | 화국반점 | 3.8 | 28,661 | 28 | 731 | 정통 중식 / 일반 중식 |
197 | 맛찬들왕소금구이 | 3.8 | 49,822 | 62 | 1,303 | 고기 요리 |
198 | 겐짱카레 | 3.8 | 22,457 | 26 | 791 | 돈부리 / 일본 카레 / 벤토 |
199 | 파크하얏트라운지 | 3.8 | 40,477 | 18 | 752 | 칵테일 / 와인 |
200 rows × 6 columns
In [6]:
# csv 파일 저장
df_all.to_csv('Busan_Mango.csv', encoding='utf-8-sig', index=False)
결측치 존재 확인¶
In [77]:
# 파일 불러오기
df_all = pd.read_csv('Busan_Mango.csv')
In [78]:
df_all.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 200 entries, 0 to 199 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 title 200 non-null object 1 Point 200 non-null float64 2 View 200 non-null int64 3 Review 200 non-null int64 4 Star 200 non-null int64 5 Type 200 non-null object dtypes: float64(1), int64(3), object(2) memory usage: 9.5+ KB
In [79]:
### 열 이름 수정
# 망고 데이터 이름 통일
df_all.rename(columns = {'title' : 'Title'}, inplace=True)
print(df_all.columns)
Index(['Title', 'Point', 'View', 'Review', 'Star', 'Type'], dtype='object')
type 열 정제¶
In [80]:
# 한글만 추출
data = df_all.copy()
data['Type'] = data['Type'].str.findall('[가-힣]+')
data['Type']
Out[80]:
0 [카페, 디저트, 오늘의, 차, 우전녹차, 특말차, 복분자, 냉, 오미자차] 1 [까스, 요리] 2 [정통, 일식, 일반, 일식, 특히츠마부시, 민물장어덮밥, 특카이센동, 해산물덮밥,... 3 [딤섬, 만두] 4 [탕, 찌개, 전골] ... 195 [카페, 디저트] 196 [정통, 중식, 일반, 중식] 197 [고기, 요리] 198 [돈부리, 일본, 카레, 벤토] 199 [칵테일, 와인] Name: Type, Length: 200, dtype: object
In [81]:
# 공백문자로 word 단위로 문자열로 반환
data['Type'] = data['Type'].apply(lambda x : (' ').join(x))
data['Type']
Out[81]:
0 카페 디저트 오늘의 차 우전녹차 특말차 복분자 냉 오미자차 1 까스 요리 2 정통 일식 일반 일식 특히츠마부시 민물장어덮밥 특카이센동 해산물덮밥 카이센동 해산물... 3 딤섬 만두 4 탕 찌개 전골 ... 195 카페 디저트 196 정통 중식 일반 중식 197 고기 요리 198 돈부리 일본 카레 벤토 199 칵테일 와인 Name: Type, Length: 200, dtype: object
In [82]:
# '원' 문자 제거
data['Type'] = data['Type'].str.replace('원', '')
data['Type']
Out[82]:
0 카페 디저트 오늘의 차 우전녹차 특말차 복분자 냉 오미자차 1 까스 요리 2 정통 일식 일반 일식 특히츠마부시 민물장어덮밥 특카이센동 해산물덮밥 카이센동 해산물... 3 딤섬 만두 4 탕 찌개 전골 ... 195 카페 디저트 196 정통 중식 일반 중식 197 고기 요리 198 돈부리 일본 카레 벤토 199 칵테일 와인 Name: Type, Length: 200, dtype: object
문자열에서 숫자형으로 변환 : View, Star 열¶
View 열 부터¶
In [83]:
# 모든 원소들을 문자형으로 반환
data['View'] = [str(x) for x in data['View']]
data['View'] = data['View'].str.replace(',', '')
print(data['View'].isna().sum(), '\n')
print(data['View'])
0 0 136578 1 26176 2 324680 3 259881 4 128996 ... 195 29192 196 28661 197 49822 198 22457 199 40477 Name: View, Length: 200, dtype: object
In [84]:
data['View'] = data['View'].astype(int)
data.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 200 entries, 0 to 199 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Title 200 non-null object 1 Point 200 non-null float64 2 View 200 non-null int32 3 Review 200 non-null int64 4 Star 200 non-null int64 5 Type 200 non-null object dtypes: float64(1), int32(1), int64(2), object(2) memory usage: 8.7+ KB
Star 열¶
In [89]:
# 모든 원소들을 문자형으로 반환
star_list = [str(x) for x in data['Star']]
data['Star'] = star_list
data['Star']
Out[89]:
0 3782 1 867 2 5477 3 5903 4 2812 ... 195 1025 196 731 197 1303 198 791 199 752 Name: Star, Length: 200, dtype: object
In [90]:
data['Star'] = data['Star'].str.replace(',', '')
print(data['Star'].isna().sum(), '\n')
print(data['Star'])
0 0 3782 1 867 2 5477 3 5903 4 2812 ... 195 1025 196 731 197 1303 198 791 199 752 Name: Star, Length: 200, dtype: object
In [91]:
data['Star'] = data['Star'].astype(int)
data.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 200 entries, 0 to 199 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Title 200 non-null object 1 Point 200 non-null float64 2 View 200 non-null int32 3 Review 200 non-null int64 4 Star 200 non-null int32 5 Type 200 non-null object dtypes: float64(1), int32(2), int64(1), object(2) memory usage: 7.9+ KB
중복 이름 처리¶
가게 이름 '톤쇼우'가 2개 있다. 그런데 점수가 다 다르다. 일단은 '톤쇼우1', '톤쇼우2'로 한다.
안 그래도 데이터 적은데 삭제하면 더 적어지니 아끼는 마음으로 삭제하지 않기로 결정한다.
In [92]:
data.loc[1, 'Title'] = '톤쇼우1'
print(data.loc[1, 'Title'])
data.loc[105, 'Title'] = '톤쇼우2'
print(data.loc[105, 'Title'])
톤쇼우1 톤쇼우2
In [93]:
#정제 완료한 데이터를 csv로 저장
data.to_csv('mango_revise.csv', encoding='utf-8-sig', index=False)
CBF 추천 알고리즘 적용¶
In [94]:
# 파일 불러오기
data = pd.read_csv('mango_revise.csv')
data.head()
Out[94]:
Title | Point | View | Review | Star | Type | |
---|---|---|---|---|---|---|
0 | 비비비당 | 4.6 | 136578 | 74 | 3782 | 카페 디저트 오늘의 차 우전녹차 특말차 복분자 냉 오미자차 |
1 | 톤쇼우1 | 4.6 | 26176 | 38 | 867 | 까스 요리 |
2 | 해목 | 4.5 | 324680 | 157 | 5477 | 정통 일식 일반 일식 특히츠마부시 민물장어덮밥 특카이센동 해산물덮밥 카이센동 해산물... |
3 | 신발원 | 4.5 | 259881 | 166 | 5903 | 딤섬 만두 |
4 | 할매국밥 | 4.5 | 128996 | 88 | 2812 | 탕 찌개 전골 |
CountVectorizer로 학습¶
In [95]:
from sklearn.feature_extraction.text import CountVectorizer
count_vect1 = CountVectorizer(min_df=1, ngram_range=(1, 2)) # min_df: 단어장에 들어갈 최소빈도, ngram_range: 1 <= n <= 2
type_mat1 = count_vect1.fit_transform(data['Type'])
print(type_mat1.shape)
print(type_mat1[:5])
# 200개 가게에 대한 307개 유형의 '유형 매트릭스'가 생성되었다.
(200, 307) (0, 236) 1 (0, 36) 1 (0, 154) 1 (0, 178) 1 (0, 257) 1 (0, 100) 1 (0, 161) 1 (0, 237) 1 (0, 39) 1 (0, 155) 1 (0, 179) 1 (0, 258) 1 (0, 101) 1 (1, 15) 1 (1, 168) 1 (1, 16) 1 (2, 209) 1 (2, 199) 2 (2, 194) 1 (2, 263) 1 (2, 75) 1 (2, 261) 1 (2, 296) 2 (2, 234) 1 (2, 118) 1 (2, 116) 1 (2, 141) 1 (2, 210) 1 (2, 200) 1 (2, 195) 1 (2, 201) 1 (2, 264) 1 (2, 76) 1 (2, 262) 1 (2, 298) 1 (2, 235) 1 (2, 297) 1 (2, 119) 1 (2, 117) 1 (3, 42) 1 (3, 64) 1 (3, 43) 1 (4, 222) 1 (4, 208) 1 (4, 223) 1
코사인 유사도(cosine_similarity)이용해서 가게별 유사도 계산¶
In [96]:
# 코사인 유사도에 의해 200개 가게 각각 유사한 가게들이 계산됨
from sklearn.metrics.pairwise import cosine_similarity
type_sim = cosine_similarity(type_mat1, type_mat1)
print(type_sim.shape)
print(type_sim)
(200, 200) [[1. 0. 0. ... 0. 0. 0. ] [0. 1. 0. ... 0.33333333 0. 0. ] [0. 0. 1. ... 0. 0. 0. ] ... [0. 0.33333333 0. ... 1. 0. 0. ] [0. 0. 0. ... 0. 1. 0. ] [0. 0. 0. ... 0. 0. 1. ]]
In [97]:
# 유사도가 높은 가게를 앞에서부터 순서대로 보여줌
# 0번째 가게의 경우 유사도 순서 : 0번, 147번, 167번, ..., 99번 순서
type_sim_sorted_ind = type_sim.argsort()[:, ::-1] # ::-1 : 역순으로 정렬
print(type_sim_sorted_ind)
[[ 0 147 167 ... 112 111 99] [ 1 105 185 ... 115 114 0] [ 2 61 8 ... 127 126 0] ... [ 85 133 30 ... 115 114 0] [198 100 57 ... 129 128 0] [199 47 15 ... 128 127 0]]
추천 ver1. 코사인 유사도에 의해 Type 비슷한 가게를 추천하는 함수¶
In [98]:
def find_sim_food_ver1(df, sorted_ind, title_name, top_n):
# 인자로 입력된 data에서 'Title' 컬럼이 입력된 title_name 값인 DataFrame추출
title_food = df[df['Title'] == title_name]
# title_name을 가진 DataFrame의 index 객체를 ndarray로 반환하고
# sorted_ind 인자로 입력된 type_sim_sorted_ind 객체에서 유사도 순으로 top_n 개의 index 추출
title_index = title_food.index.values
similar_indices = sorted_ind[title_index, :(top_n)]
# 추출된 top_n index들 출력. top_n index는 2차원 데이터 임.
# dataframe에서 index로 사용하기 위해서 1차원 array로 변경
print(similar_indices)
# 2차원 데이터를 1차원으로 변환
similar_indices = similar_indices.reshape(-1)
return df.iloc[similar_indices]
가게 '비비비당'과 유형이 유사한 가게 10개 추천¶
In [99]:
similar_foods = find_sim_food_ver1(data, type_sim_sorted_ind, '비비비당', top_n=10)
similar_foods
[[ 0 147 167 166 161 108 25 62 153 149]]
Out[99]:
Title | Point | View | Review | Star | Type | |
---|---|---|---|---|---|---|
0 | 비비비당 | 4.6 | 136578 | 74 | 3782 | 카페 디저트 오늘의 차 우전녹차 특말차 복분자 냉 오미자차 |
147 | 에쎄떼 | 3.9 | 13494 | 10 | 373 | 카페 디저트 |
167 | 쿠루미과자점 | 3.9 | 4313 | 9 | 120 | 카페 디저트 |
166 | 그릿비 일광 | 3.9 | 15623 | 11 | 399 | 카페 디저트 |
161 | 에테르 | 3.9 | 4713 | 13 | 119 | 카페 디저트 |
108 | Cafe de 220VOLT | 4.0 | 6364 | 9 | 157 | 카페 디저트 |
25 | 흰여울비치 | 4.3 | 2323 | 7 | 66 | 카페 디저트 |
62 | 이너프 | 4.1 | 56636 | 23 | 1924 | 카페 디저트 |
153 | 문화공감 수정 | 3.9 | 8379 | 14 | 156 | 카페 디저트 |
149 | 보느파티쓰리 | 3.9 | 9292 | 10 | 305 | 카페 디저트 |
In [100]:
# Point 기준 내림차순 정렬
similar_foods.sort_values(by='Point', ascending=False)
Out[100]:
Title | Point | View | Review | Star | Type | |
---|---|---|---|---|---|---|
0 | 비비비당 | 4.6 | 136578 | 74 | 3782 | 카페 디저트 오늘의 차 우전녹차 특말차 복분자 냉 오미자차 |
25 | 흰여울비치 | 4.3 | 2323 | 7 | 66 | 카페 디저트 |
62 | 이너프 | 4.1 | 56636 | 23 | 1924 | 카페 디저트 |
108 | Cafe de 220VOLT | 4.0 | 6364 | 9 | 157 | 카페 디저트 |
147 | 에쎄떼 | 3.9 | 13494 | 10 | 373 | 카페 디저트 |
167 | 쿠루미과자점 | 3.9 | 4313 | 9 | 120 | 카페 디저트 |
166 | 그릿비 일광 | 3.9 | 15623 | 11 | 399 | 카페 디저트 |
161 | 에테르 | 3.9 | 4713 | 13 | 119 | 카페 디저트 |
153 | 문화공감 수정 | 3.9 | 8379 | 14 | 156 | 카페 디저트 |
149 | 보느파티쓰리 | 3.9 | 9292 | 10 | 305 | 카페 디저트 |
가중평점을 만들기¶
1) MinMaxScale를 통해 0~1
로 값의 규모를 통일시킨다.
2) 행 기준으로 점수를 더한다.
In [101]:
data.head(3)
Out[101]:
Title | Point | View | Review | Star | Type | |
---|---|---|---|---|---|---|
0 | 비비비당 | 4.6 | 136578 | 74 | 3782 | 카페 디저트 오늘의 차 우전녹차 특말차 복분자 냉 오미자차 |
1 | 톤쇼우1 | 4.6 | 26176 | 38 | 867 | 까스 요리 |
2 | 해목 | 4.5 | 324680 | 157 | 5477 | 정통 일식 일반 일식 특히츠마부시 민물장어덮밥 특카이센동 해산물덮밥 카이센동 해산물... |
In [102]:
# 0~1로 스케일 조정
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
data[['Point', 'View', 'Review', 'Star']] = scaler.fit_transform(data[['Point', 'View', 'Review', 'Star']])
data[['Point', 'View', 'Review', 'Star']]
Out[102]:
Point | View | Review | Star | |
---|---|---|---|---|
0 | 1.000 | 0.420429 | 0.297872 | 0.60480 |
1 | 1.000 | 0.080264 | 0.144681 | 0.13840 |
2 | 0.875 | 1.000000 | 0.651064 | 0.87600 |
3 | 0.875 | 0.800344 | 0.689362 | 0.94416 |
4 | 0.875 | 0.397068 | 0.357447 | 0.44960 |
... | ... | ... | ... | ... |
195 | 0.000 | 0.089557 | 0.093617 | 0.16368 |
196 | 0.000 | 0.087921 | 0.102128 | 0.11664 |
197 | 0.000 | 0.153121 | 0.246809 | 0.20816 |
198 | 0.000 | 0.068805 | 0.093617 | 0.12624 |
199 | 0.000 | 0.124328 | 0.059574 | 0.12000 |
200 rows × 4 columns
In [103]:
data.head()
Out[103]:
Title | Point | View | Review | Star | Type | |
---|---|---|---|---|---|---|
0 | 비비비당 | 1.000 | 0.420429 | 0.297872 | 0.60480 | 카페 디저트 오늘의 차 우전녹차 특말차 복분자 냉 오미자차 |
1 | 톤쇼우1 | 1.000 | 0.080264 | 0.144681 | 0.13840 | 까스 요리 |
2 | 해목 | 0.875 | 1.000000 | 0.651064 | 0.87600 | 정통 일식 일반 일식 특히츠마부시 민물장어덮밥 특카이센동 해산물덮밥 카이센동 해산물... |
3 | 신발원 | 0.875 | 0.800344 | 0.689362 | 0.94416 | 딤섬 만두 |
4 | 할매국밥 | 0.875 | 0.397068 | 0.357447 | 0.44960 | 탕 찌개 전골 |
In [104]:
# 행 기준으로 더하기
data['weighted_rate'] = data['Point'] + data['View'] + data['Review'] + data['Star']
data.head()
Out[104]:
Title | Point | View | Review | Star | Type | weighted_rate | |
---|---|---|---|---|---|---|---|
0 | 비비비당 | 1.000 | 0.420429 | 0.297872 | 0.60480 | 카페 디저트 오늘의 차 우전녹차 특말차 복분자 냉 오미자차 | 2.323102 |
1 | 톤쇼우1 | 1.000 | 0.080264 | 0.144681 | 0.13840 | 까스 요리 | 1.363345 |
2 | 해목 | 0.875 | 1.000000 | 0.651064 | 0.87600 | 정통 일식 일반 일식 특히츠마부시 민물장어덮밥 특카이센동 해산물덮밥 카이센동 해산물... | 3.402064 |
3 | 신발원 | 0.875 | 0.800344 | 0.689362 | 0.94416 | 딤섬 만두 | 3.308866 |
4 | 할매국밥 | 0.875 | 0.397068 | 0.357447 | 0.44960 | 탕 찌개 전골 | 2.079115 |
In [105]:
# weighted_rate의 범위 파악 : 최소값은 0.13, 최대값은 3.402
data.describe()
Out[105]:
Point | View | Review | Star | weighted_rate | |
---|---|---|---|---|---|
count | 200.000000 | 200.000000 | 200.000000 | 200.000000 | 200.000000 |
mean | 0.325625 | 0.109531 | 0.112085 | 0.138252 | 0.685493 |
std | 0.226224 | 0.151992 | 0.161075 | 0.173369 | 0.582709 |
min | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.130722 |
25% | 0.125000 | 0.023869 | 0.025532 | 0.028520 | 0.340668 |
50% | 0.250000 | 0.057044 | 0.055319 | 0.074240 | 0.526936 |
75% | 0.500000 | 0.137284 | 0.128723 | 0.172520 | 0.815072 |
max | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 3.402064 |
추천 ver2. 먼저 Type 유사성 높은 가게 20개 선정 후(F1), 가중평점순 10개 선정(F2)¶
In [106]:
def find_sim_food_ver2(df, sorted_ind, title_name, top_n):
title_food = df[df['Title'] == title_name]
title_index = title_food.index.values
# top_n의 2배에 해당하는 쟝르 유사성이 높은 index 추출
similar_indices = sorted_ind[title_index, :(top_n*2)]
similar_indices = similar_indices.reshape(-1)
# 자기 자신 가게 index는 제외
similar_indices = similar_indices[similar_indices != title_index]
# top_n의 2배에 해당하는 후보군에서 weighted_rate 높은 순으로 top_n 만큼 추출
return df.iloc[similar_indices].sort_values('weighted_rate', ascending=False)[:top_n]
가게 '비비비당'에 대해 유형 유사성, 가중평점 반영한 추천 가게 10개를 뽑아보자¶
In [107]:
similar_foods = find_sim_food_ver2(data, type_sim_sorted_ind, '비비비당', top_n=10)
similar_foods
Out[107]:
Title | Point | View | Review | Star | Type | weighted_rate | |
---|---|---|---|---|---|---|---|
53 | 블랙업커피 | 0.375 | 0.257446 | 0.387234 | 0.36416 | 카페 디저트 | 1.383840 |
38 | 보성녹차 | 0.500 | 0.137820 | 0.170213 | 0.23760 | 카페 디저트 | 1.045633 |
62 | 이너프 | 0.375 | 0.174116 | 0.080851 | 0.30752 | 카페 디저트 | 0.937487 |
25 | 흰여울비치 | 0.625 | 0.006769 | 0.012766 | 0.01024 | 카페 디저트 | 0.654775 |
43 | 샬롯 | 0.500 | 0.036345 | 0.038298 | 0.06848 | 카페 디저트 | 0.643123 |
41 | 구프 | 0.500 | 0.008621 | 0.012766 | 0.02288 | 카페 디저트 | 0.544267 |
138 | 손목서가 | 0.125 | 0.061001 | 0.068085 | 0.08448 | 카페 디저트 | 0.338566 |
108 | Cafe de 220VOLT | 0.250 | 0.019220 | 0.021277 | 0.02480 | 카페 디저트 | 0.315297 |
117 | 카페덕미 | 0.250 | 0.003756 | 0.008511 | 0.00576 | 카페 디저트 | 0.268027 |
166 | 그릿비 일광 | 0.125 | 0.047749 | 0.029787 | 0.06352 | 카페 디저트 | 0.266056 |
가게 '해목'에 대해 유형 유사성, 가중평점 반영한 추천 가게 10개를 뽑아보자¶
In [108]:
similar_foods = find_sim_food_ver2(data, type_sim_sorted_ind, '해목', top_n=10)
similar_foods
Out[108]:
Title | Point | View | Review | Star | Type | weighted_rate | |
---|---|---|---|---|---|---|---|
8 | 마가만두 | 0.750 | 0.346186 | 0.395745 | 0.46848 | 정통 중식 일반 중식 | 1.960411 |
59 | 국제밀면 | 0.375 | 0.222776 | 0.221277 | 0.33872 | 국수 면 요리 | 1.157773 |
5 | 라호짬뽕 | 0.875 | 0.068907 | 0.029787 | 0.08224 | 정통 중식 일반 중식 | 1.055934 |
70 | 풍원장미역국정찬 | 0.375 | 0.250991 | 0.131915 | 0.29536 | 한정식 백반 정통 한식 | 1.053265 |
66 | 빨간떡볶이 | 0.375 | 0.203861 | 0.127660 | 0.25248 | 기타 한식 | 0.959001 |
62 | 이너프 | 0.375 | 0.174116 | 0.080851 | 0.30752 | 카페 디저트 | 0.937487 |
69 | 풍원장 꼬막정식 | 0.375 | 0.106719 | 0.089362 | 0.15360 | 해산물 요리 | 0.724680 |
94 | 라라관 | 0.250 | 0.147522 | 0.114894 | 0.15120 | 정통 중식 일반 중식 | 0.663616 |
68 | 미청식당 | 0.375 | 0.091575 | 0.059574 | 0.13392 | 한정식 백반 정통 한식 | 0.660069 |
63 | 수변최고돼지국밥 | 0.375 | 0.056863 | 0.110638 | 0.07936 | 탕 찌개 전골 | 0.621861 |
가게 '맛찬들왕소금구이'에 대해 유형 유사성, 가중평점 반영한 추천 가게 10개를 뽑아보자¶
In [109]:
similar_foods = find_sim_food_ver2(data, type_sim_sorted_ind, '맛찬들왕소금구이', top_n=10)
similar_foods
Out[109]:
Title | Point | View | Review | Star | Type | weighted_rate | |
---|---|---|---|---|---|---|---|
17 | 해운대소문난암소갈비집 | 0.625 | 0.722672 | 0.753191 | 0.78272 | 고기 요리 | 2.883583 |
19 | 거대갈비 | 0.625 | 0.235637 | 0.110638 | 0.17312 | 고기 요리 | 1.144396 |
28 | 달인막창 | 0.625 | 0.106746 | 0.042553 | 0.08992 | 고기 요리 달인막창세트 한우막창구이 한우대창구이 한우곱창구이 한우염통구이 | 0.864220 |
133 | 해성막창집 | 0.125 | 0.132428 | 0.285106 | 0.26480 | 고기 요리 | 0.807334 |
27 | 초필살돼지구이 | 0.625 | 0.051335 | 0.042553 | 0.06848 | 고기 요리 | 0.787368 |
30 | 문화양곱창 | 0.625 | 0.041543 | 0.034043 | 0.07248 | 고기 요리 | 0.773066 |
46 | 목장원 | 0.500 | 0.039781 | 0.021277 | 0.01984 | 고기 요리 | 0.580897 |
135 | 백화양곱창 | 0.125 | 0.088244 | 0.191489 | 0.12224 | 고기 요리 | 0.526974 |
52 | 우봉 | 0.500 | 0.009108 | 0.008511 | 0.00928 | 고기 요리 | 0.526899 |
107 | 옛날오막집 | 0.250 | 0.084300 | 0.042553 | 0.11344 | 고기 요리 | 0.490293 |
가게 '톤쇼우1'에 대해 유형 유사성, 가중평점 반영한 추천 가게 10개를 뽑아보자¶
In [110]:
similar_foods = find_sim_food_ver2(data, type_sim_sorted_ind, '톤쇼우1', top_n=10)
similar_foods
Out[110]:
Title | Point | View | Review | Star | Type | weighted_rate | |
---|---|---|---|---|---|---|---|
40 | 할매집원조복국 | 0.500 | 0.218186 | 0.097872 | 0.28240 | 해산물 요리 | 1.098458 |
152 | 속씨원한대구탕 | 0.125 | 0.202937 | 0.400000 | 0.31440 | 해산물 요리 | 1.042337 |
44 | 제일산꼼장어장어구이 | 0.500 | 0.134705 | 0.063830 | 0.14944 | 해산물 요리 | 0.847975 |
30 | 문화양곱창 | 0.625 | 0.041543 | 0.034043 | 0.07248 | 고기 요리 | 0.773066 |
151 | 기장손칼국수 | 0.125 | 0.147408 | 0.204255 | 0.26304 | 국수 면 요리 | 0.739704 |
33 | 바릇식당 | 0.625 | 0.013378 | 0.008511 | 0.01856 | 해산물 요리 | 0.665449 |
48 | 대쿠이 | 0.500 | 0.033594 | 0.055319 | 0.05632 | 까스 요리 쿠이모듬카츠 | 0.645233 |
46 | 목장원 | 0.500 | 0.039781 | 0.021277 | 0.01984 | 고기 요리 | 0.580897 |
42 | 초원복국 | 0.500 | 0.023685 | 0.038298 | 0.01872 | 해산물 요리 | 0.580703 |
146 | 이름난기장산곰장어 | 0.125 | 0.148025 | 0.102128 | 0.16096 | 해산물 요리 | 0.536112 |
추천 ver3. 먼저 유형 유사성 높은 가게 20개 선정 후(F1), 가중평점(2)순 10개 선정(F2)¶
In [111]:
def weighted_rate_average(record):
v = record['Review']
R = record['Point']
return ( (v/(v+m)) * R ) + ( (m/(m+v)) * C )
C = data['Point'].mean()
m = data['Review'].quantile(0.6)
data['weighted_rate2'] = data.apply(weighted_rate_average, axis=1)
data['weighted_rate2'] = data['weighted_rate2'] * 10 # 이미 0~1사이 이므로 보기 쉽게 10을 곱함
In [112]:
# weighted_rate2의 범위 파악 : 최소값은 0.308, 최대값은 8.745
data.describe()
Out[112]:
Point | View | Review | Star | weighted_rate | weighted_rate2 | |
---|---|---|---|---|---|---|
count | 200.000000 | 200.000000 | 200.000000 | 200.000000 | 200.000000 | 200.000000 |
mean | 0.325625 | 0.109531 | 0.112085 | 0.138252 | 0.685493 | 3.317181 |
std | 0.226224 | 0.151992 | 0.161075 | 0.173369 | 0.582709 | 1.380356 |
min | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.130722 | 0.308284 |
25% | 0.125000 | 0.023869 | 0.025532 | 0.028520 | 0.340668 | 2.661661 |
50% | 0.250000 | 0.057044 | 0.055319 | 0.074240 | 0.526936 | 3.041667 |
75% | 0.500000 | 0.137284 | 0.128723 | 0.172520 | 0.815072 | 3.592917 |
max | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 3.402064 | 8.745349 |
In [113]:
def find_sim_food_ver3(df, sorted_ind, title_name, top_n):
title_food = df[df['Title'] == title_name]
title_index = title_food.index.values
# top_n의 2배에 해당하는 쟝르 유사성이 높은 index 추출
similar_indices = sorted_ind[title_index, :(top_n*2)]
similar_indices = similar_indices.reshape(-1)
# 자기 자신 가게 index는 제외
similar_indices = similar_indices[similar_indices != title_index]
# top_n의 2배에 해당하는 후보군에서 weighted_rate2 높은 순으로 top_n 만큼 추출
return df.iloc[similar_indices].sort_values('weighted_rate2', ascending=False)[:top_n]
가게 '비비비당'에 대해 유형 유사성, 가중평점(2) 반영한 추천 가게 10개를 뽑아보자¶
In [114]:
similar_foods = find_sim_food_ver3(data, type_sim_sorted_ind, '비비비당', top_n=10)
similar_foods
Out[114]:
Title | Point | View | Review | Star | Type | weighted_rate | weighted_rate2 | |
---|---|---|---|---|---|---|---|---|
38 | 보성녹차 | 0.500 | 0.137820 | 0.170213 | 0.23760 | 카페 디저트 | 1.045633 | 4.501786 |
43 | 샬롯 | 0.500 | 0.036345 | 0.038298 | 0.06848 | 카페 디저트 | 0.643123 | 3.884000 |
25 | 흰여울비치 | 0.625 | 0.006769 | 0.012766 | 0.01024 | 카페 디저트 | 0.654775 | 3.728947 |
53 | 블랙업커피 | 0.375 | 0.257446 | 0.387234 | 0.36416 | 카페 디저트 | 1.383840 | 3.676168 |
41 | 구프 | 0.500 | 0.008621 | 0.012766 | 0.02288 | 카페 디저트 | 0.544267 | 3.531579 |
62 | 이너프 | 0.375 | 0.174116 | 0.080851 | 0.30752 | 카페 디저트 | 0.937487 | 3.524286 |
115 | 수월경화 | 0.250 | 0.002884 | 0.004255 | 0.00640 | 카페 디저트 | 0.263539 | 3.211765 |
117 | 카페덕미 | 0.250 | 0.003756 | 0.008511 | 0.00576 | 카페 디저트 | 0.268027 | 3.172222 |
108 | Cafe de 220VOLT | 0.250 | 0.019220 | 0.021277 | 0.02480 | 카페 디저트 | 0.315297 | 3.076190 |
148 | 어라이크커피 | 0.125 | 0.026119 | 0.017021 | 0.04608 | 카페 디저트 | 0.214220 | 2.855000 |
가게 '해목'에 대해 유형 유사성, 가중평점(2) 반영한 추천 가게 10개를 뽑아보자¶
In [115]:
similar_foods = find_sim_food_ver3(data, type_sim_sorted_ind, '해목', top_n=10)
similar_foods
Out[115]:
Title | Point | View | Review | Star | Type | weighted_rate | weighted_rate2 | |
---|---|---|---|---|---|---|---|---|
8 | 마가만두 | 0.750 | 0.346186 | 0.395745 | 0.46848 | 정통 중식 일반 중식 | 1.960411 | 6.877064 |
5 | 라호짬뽕 | 0.875 | 0.068907 | 0.029787 | 0.08224 | 정통 중식 일반 중식 | 1.055934 | 4.928261 |
59 | 국제밀면 | 0.375 | 0.222776 | 0.221277 | 0.33872 | 국수 면 요리 | 1.157773 | 3.633824 |
70 | 풍원장미역국정찬 | 0.375 | 0.250991 | 0.131915 | 0.29536 | 한정식 백반 정통 한식 | 1.053265 | 3.581915 |
66 | 빨간떡볶이 | 0.375 | 0.203861 | 0.127660 | 0.25248 | 기타 한식 | 0.959001 | 3.578261 |
63 | 수변최고돼지국밥 | 0.375 | 0.056863 | 0.110638 | 0.07936 | 탕 찌개 전골 | 0.621861 | 3.561905 |
69 | 풍원장 꼬막정식 | 0.375 | 0.106719 | 0.089362 | 0.15360 | 해산물 요리 | 0.724680 | 3.536486 |
62 | 이너프 | 0.375 | 0.174116 | 0.080851 | 0.30752 | 카페 디저트 | 0.937487 | 3.524286 |
67 | 봉샌드 | 0.375 | 0.055784 | 0.072340 | 0.07200 | 브런치 버거 샌드위치 | 0.575125 | 3.510606 |
68 | 미청식당 | 0.375 | 0.091575 | 0.059574 | 0.13392 | 한정식 백반 정통 한식 | 0.660069 | 3.486667 |
가게 '맛찬들왕소금구이'에 대해 유형 유사성, 가중평점(2) 반영한 추천 가게 10개를 뽑아보자¶
In [116]:
similar_foods = find_sim_food_ver3(data, type_sim_sorted_ind, '맛찬들왕소금구이', top_n=10)
similar_foods
Out[116]:
Title | Point | View | Review | Star | Type | weighted_rate | weighted_rate2 | |
---|---|---|---|---|---|---|---|---|
17 | 해운대소문난암소갈비집 | 0.625 | 0.722672 | 0.753191 | 0.78272 | 고기 요리 | 2.883583 | 6.001813 |
19 | 거대갈비 | 0.625 | 0.235637 | 0.110638 | 0.17312 | 고기 요리 | 1.144396 | 5.109524 |
27 | 초필살돼지구이 | 0.625 | 0.051335 | 0.042553 | 0.06848 | 고기 요리 | 0.787368 | 4.407692 |
28 | 달인막창 | 0.625 | 0.106746 | 0.042553 | 0.08992 | 고기 요리 달인막창세트 한우막창구이 한우대창구이 한우곱창구이 한우염통구이 | 0.864220 | 4.407692 |
30 | 문화양곱창 | 0.625 | 0.041543 | 0.034043 | 0.07248 | 고기 요리 | 0.773066 | 4.254167 |
46 | 목장원 | 0.500 | 0.039781 | 0.021277 | 0.01984 | 고기 요리 | 0.580897 | 3.671429 |
52 | 우봉 | 0.500 | 0.009108 | 0.008511 | 0.00928 | 고기 요리 | 0.526899 | 3.450000 |
85 | 대도식당 | 0.375 | 0.036090 | 0.012766 | 0.02304 | 고기 요리 | 0.446895 | 3.334211 |
124 | 광안리막창집 | 0.250 | 0.023888 | 0.038298 | 0.03904 | 고기 요리 | 0.351226 | 2.984000 |
107 | 옛날오막집 | 0.250 | 0.084300 | 0.042553 | 0.11344 | 고기 요리 | 0.490293 | 2.965385 |
가게 '톤쇼우1'에 대해 유형 유사성, 가중평점 반영한 추천 가게 10개를 뽑아보자¶
In [117]:
similar_foods = find_sim_food_ver3(data, type_sim_sorted_ind, '톤쇼우1', top_n=10)
similar_foods
Out[117]:
Title | Point | View | Review | Star | Type | weighted_rate | weighted_rate2 | |
---|---|---|---|---|---|---|---|---|
40 | 할매집원조복국 | 0.500 | 0.218186 | 0.097872 | 0.28240 | 해산물 요리 | 1.098458 | 4.284615 |
30 | 문화양곱창 | 0.625 | 0.041543 | 0.034043 | 0.07248 | 고기 요리 | 0.773066 | 4.254167 |
44 | 제일산꼼장어장어구이 | 0.500 | 0.134705 | 0.063830 | 0.14944 | 해산물 요리 | 0.847975 | 4.100000 |
48 | 대쿠이 | 0.500 | 0.033594 | 0.055319 | 0.05632 | 까스 요리 쿠이모듬카츠 | 0.645233 | 4.037931 |
42 | 초원복국 | 0.500 | 0.023685 | 0.038298 | 0.01872 | 해산물 요리 | 0.580703 | 3.884000 |
46 | 목장원 | 0.500 | 0.039781 | 0.021277 | 0.01984 | 고기 요리 | 0.580897 | 3.671429 |
33 | 바릇식당 | 0.625 | 0.013378 | 0.008511 | 0.01856 | 해산물 요리 | 0.665449 | 3.588889 |
84 | 냉수탕가든 | 0.375 | 0.017698 | 0.025532 | 0.02720 | 닭 오리 요리 | 0.445430 | 3.390909 |
85 | 대도식당 | 0.375 | 0.036090 | 0.012766 | 0.02304 | 고기 요리 | 0.446895 | 3.334211 |
185 | 유일한식탁 | 0.125 | 0.007167 | 0.008511 | 0.00704 | 까스 요리 | 0.147717 | 3.033333 |
가중평점(2) 기준으로 top 10 가게¶
In [118]:
data.sort_values('weighted_rate2', ascending=False).head(10)
Out[118]:
Title | Point | View | Review | Star | Type | weighted_rate | weighted_rate2 | |
---|---|---|---|---|---|---|---|---|
0 | 비비비당 | 1.000 | 0.420429 | 0.297872 | 0.60480 | 카페 디저트 오늘의 차 우전녹차 특말차 복분자 냉 오미자차 | 2.323102 | 8.745349 |
3 | 신발원 | 0.875 | 0.800344 | 0.689362 | 0.94416 | 딤섬 만두 | 3.308866 | 8.256180 |
2 | 해목 | 0.875 | 1.000000 | 0.651064 | 0.87600 | 정통 일식 일반 일식 특히츠마부시 민물장어덮밥 특카이센동 해산물덮밥 카이센동 해산물... | 3.402064 | 8.229882 |
4 | 할매국밥 | 0.875 | 0.397068 | 0.357447 | 0.44960 | 탕 찌개 전골 | 2.079115 | 7.871000 |
1 | 톤쇼우1 | 1.000 | 0.080264 | 0.144681 | 0.13840 | 까스 요리 | 1.363345 | 7.842000 |
7 | 이재모피자 | 0.750 | 0.498238 | 0.919149 | 0.65232 | 기타 양식 이재모치즈크러스트피자 이재모치즈크러스트피자 이재모불고기피자 이재모불고기피... | 2.819707 | 7.207328 |
9 | 블랙업커피 | 0.750 | 0.553865 | 0.463830 | 0.55632 | 카페 디저트 | 2.324014 | 6.956800 |
8 | 마가만두 | 0.750 | 0.346186 | 0.395745 | 0.46848 | 정통 중식 일반 중식 | 1.960411 | 6.877064 |
10 | 고옥 | 0.750 | 0.698010 | 0.323404 | 0.66592 | 돈부리 일본 카레 벤토 | 2.437334 | 6.761957 |
11 | 나가하마만게츠 | 0.750 | 0.196879 | 0.204255 | 0.29952 | 라멘 소바 우동 나가하마라멘 야끼라멘 오분야끼교자 나가히마라멘교자 세트 | 1.450655 | 6.439063 |
Type 정제한 데이터로 CBF 수행¶
In [3]:
# 파일 불러오기
data = pd.read_csv('CsvFile/mango_konlpy.csv')
data.head()
Out[3]:
Unnamed: 0 | Title | Point | Review | weighted_rating | View | Star | Type | Site | |
---|---|---|---|---|---|---|---|---|---|
0 | 0 | 비비비당 | 4.6 | 74 | 4.485213 | 136578 | 3782 | 카페 디저트 차 우전 녹차 특 말차 복분자 냉 오미자차 | mango |
1 | 1 | 신발원 | 4.5 | 166 | 4.452742 | 259881 | 5903 | 딤섬 만두 | mango |
2 | 2 | 해목 | 4.5 | 157 | 4.450339 | 324680 | 5477 | 정통 일식 일식 츠마 부시 민물장어 밥 특 카이센동 해산물 밥 카이센동 해산물 밥 ... | mango |
3 | 3 | 할매국밥 | 4.5 | 88 | 4.418611 | 128996 | 2812 | 탕 찌개 전골 | mango |
4 | 4 | 톤쇼우 | 4.6 | 38 | 4.413966 | 26176 | 867 | 까스 | mango |
In [4]:
from sklearn.feature_extraction.text import CountVectorizer
count_vect1 = CountVectorizer(min_df=1, ngram_range=(1, 2)) # min_df: 단어장에 들어갈 최소빈도, ngram_range: 1 <= n <= 2
type_mat1 = count_vect1.fit_transform(data['Type'])
print(type_mat1.shape)
print(type_mat1[:5])
# 200개 가게에 대한 335개 유형의 '유형 매트릭스'가 생성되었다.
(200, 335) (0, 250) 1 (0, 35) 1 (0, 192) 1 (0, 26) 1 (0, 79) 1 (0, 113) 1 (0, 178) 1 (0, 251) 1 (0, 38) 1 (0, 193) 1 (0, 27) 1 (0, 80) 1 (0, 114) 1 (1, 41) 1 (1, 78) 1 (1, 42) 1 (2, 218) 1 (2, 204) 2 (2, 233) 1 (2, 117) 1 (2, 88) 1 (2, 247) 2 (2, 322) 2 (2, 170) 2 (2, 158) 1 (2, 219) 1 (2, 205) 1 (2, 206) 1 (2, 234) 1 (2, 118) 1 (2, 89) 1 (2, 248) 2 (2, 324) 1 (2, 323) 1 (2, 172) 1 (2, 171) 1 (3, 227) 1 (3, 213) 1 (3, 228) 1 (4, 20) 1
In [5]:
# 코사인 유사도에 의해 200개 가게 각각 유사한 가게들이 계산됨
from sklearn.metrics.pairwise import cosine_similarity
type_sim = cosine_similarity(type_mat1, type_mat1)
print(type_sim.shape)
print(type_sim)
(200, 200) [[1. 0. 0. ... 0. 0. 0.] [0. 1. 0. ... 0. 0. 0.] [0. 0. 1. ... 0. 0. 0.] ... [0. 0. 0. ... 1. 0. 0.] [0. 0. 0. ... 0. 1. 0.] [0. 0. 0. ... 0. 0. 1.]]
In [6]:
# 유사도가 높은 가게를 앞에서부터 순서대로 보여줌
# 0번째 가게의 경우 유사도 순서 : 0번, 169번, 163번, ..., 99번 순서
type_sim_sorted_ind = type_sim.argsort()[:, ::-1] # ::-1 : 역순으로 정렬
print(type_sim_sorted_ind)
[[ 0 169 163 ... 116 115 99] [ 1 171 25 ... 127 126 0] [ 2 77 24 ... 126 125 0] ... [141 103 26 ... 124 123 0] [ 23 104 33 ... 125 124 0] [199 166 115 ... 125 124 0]]
In [8]:
def find_sim_food_ver4(df, sorted_ind, title_name, top_n):
title_food = df[df['Title'] == title_name]
title_index = title_food.index.values
# top_n의 2배에 해당하는 쟝르 유사성이 높은 index 추출
similar_indices = sorted_ind[title_index, :(top_n*2)]
similar_indices = similar_indices.reshape(-1)
# 자기 자신 가게 index는 제외
similar_indices = similar_indices[similar_indices != title_index]
# top_n의 2배에 해당하는 후보군에서 weighted_rate2 높은 순으로 top_n 만큼 추출
return df.iloc[similar_indices].sort_values('weighted_rating', ascending=False)[:top_n]
가게 '비비비당'에 대해 유형 유사성, 가중평점 반영한 추천 가게 10개를 뽑아보자¶
In [11]:
similar_foods = find_sim_food_ver4(data, type_sim_sorted_ind, '비비비당', top_n=10)
similar_foods.iloc[:, 1:]
Out[11]:
Title | Point | Review | weighted_rating | View | Star | Type | Site | |
---|---|---|---|---|---|---|---|---|
29 | 보성녹차 | 4.2 | 44 | 4.156406 | 44856 | 1487 | 카페 디저트 | mango |
38 | 흰여울비치 | 4.3 | 7 | 4.122593 | 2323 | 66 | 카페 디저트 | mango |
42 | 샬롯 | 4.2 | 13 | 4.115455 | 11922 | 430 | 카페 디저트 | mango |
50 | 구프 | 4.2 | 7 | 4.096667 | 2924 | 145 | 카페 디저트 | mango |
51 | 블랙업커피 | 4.1 | 95 | 4.093130 | 83681 | 2278 | 카페 디저트 | mango |
129 | 모모스커피 | 4.0 | 38 | 4.020862 | 21292 | 544 | 카페 디저트 | mango |
131 | 카페38.5 | 3.9 | 7 | 4.018889 | 1405 | 20 | 카페 디저트 | mango |
136 | 어라이크커피 | 3.9 | 8 | 4.014643 | 8603 | 290 | 카페 디저트 | mango |
143 | 어바웃제이 | 3.9 | 9 | 4.010690 | 6251 | 141 | 카페 디저트 | mango |
144 | 쿠루미과자점 | 3.9 | 9 | 4.010690 | 4313 | 120 | 카페 디저트 | mango |
가게 '수변최고돼지국밥'에 대해 유형 유사성, 가중평점 반영한 추천 가게 10개를 뽑아보자¶
In [15]:
similar_foods = find_sim_food_ver4(data, type_sim_sorted_ind, '수변최고돼지국밥', top_n=10)
similar_foods.iloc[:, 1:]
Out[15]:
Title | Point | Review | weighted_rating | View | Star | Type | Site | |
---|---|---|---|---|---|---|---|---|
3 | 할매국밥 | 4.5 | 88 | 4.418611 | 128996 | 2812 | 탕 찌개 전골 | mango |
23 | 밀양순대돼지국밥 | 4.2 | 92 | 4.175089 | 99967 | 2251 | 탕 찌개 전골 | mango |
33 | 합천국밥집 | 4.2 | 20 | 4.130250 | 14969 | 498 | 탕 찌개 전골 | mango |
34 | 소문난돼지국밥 | 4.3 | 8 | 4.128929 | 9952 | 291 | 탕 찌개 전골 | mango |
41 | 거대곰탕 | 4.3 | 6 | 4.115769 | 2592 | 49 | 탕 찌개 전골 | mango |
45 | 바로해장 | 4.3 | 5 | 4.108400 | 846 | 43 | 탕 찌개 전골 | mango |
76 | 거대곰탕 | 4.1 | 11 | 4.074516 | 12748 | 330 | 탕 찌개 전골 | mango |
98 | 공순대 | 4.0 | 12 | 4.037812 | 9784 | 235 | 탕 찌개 전골 | mango |
104 | 왔다식당 | 4.0 | 14 | 4.035588 | 12432 | 252 | 탕 찌개 전골 | mango |
112 | 자매국밥 | 4.0 | 17 | 4.032703 | 16311 | 389 | 탕 찌개 전골 | mango |
가게 '기와집대구탕'에 대해 유형 유사성, 가중평점 반영한 추천 가게 10개를 뽑아보자¶
In [16]:
similar_foods = find_sim_food_ver4(data, type_sim_sorted_ind, '기와집대구탕', top_n=10)
similar_foods.iloc[:, 1:]
Out[16]:
Title | Point | Review | weighted_rating | View | Star | Type | Site | |
---|---|---|---|---|---|---|---|---|
13 | 금수복국 | 4.3 | 154 | 4.272471 | 110960 | 2710 | 해산물 | mango |
14 | 동백섬횟집 | 4.4 | 22 | 4.238333 | 80262 | 1641 | 해산물 | mango |
19 | 명성횟집 | 4.3 | 29 | 4.202245 | 85428 | 1849 | 해산물 | mango |
24 | 선창횟집 | 4.3 | 18 | 4.173947 | 49924 | 879 | 해산물 | mango |
32 | 할매집원조복국 | 4.2 | 27 | 4.140638 | 70939 | 1767 | 해산물 | mango |
35 | 제일산꼼장어장어구이 | 4.2 | 19 | 4.128462 | 43845 | 936 | 해산물 | mango |
40 | 바릇식당 | 4.3 | 6 | 4.115769 | 4468 | 118 | 해산물 | mango |
43 | 초원복국 | 4.2 | 13 | 4.115455 | 7813 | 119 | 해산물 | mango |
47 | 일광대복집 | 4.2 | 8 | 4.100357 | 2932 | 47 | 해산물 | mango |
62 | 풍원장 꼬막정식 | 4.1 | 25 | 4.082444 | 34762 | 962 | 해산물 | mango |
가게 '이재모피자'에 대해 유형 유사성, 가중평점 반영한 추천 가게 10개를 뽑아보자¶
In [13]:
similar_foods = find_sim_food_ver4(data, type_sim_sorted_ind, '이재모피자', top_n=10)
similar_foods.iloc[:, 1:]
Out[13]:
Title | Point | Review | weighted_rating | View | Star | Type | Site | |
---|---|---|---|---|---|---|---|---|
15 | 포르타나 | 4.5 | 13 | 4.233636 | 25505 | 608 | 양식 마르 게리 후라이드 치킨 | mango |
31 | 버거샵 | 4.3 | 11 | 4.145484 | 3621 | 127 | 브런치 버거 샌드위치 클래식 버거 치즈버거 베이컨 치즈 감자 튀김 하리 토스 | mango |
59 | 빨간떡볶이 | 4.1 | 34 | 4.085370 | 66290 | 1580 | 한식 | mango |
60 | 수변최고돼지국밥 | 4.1 | 30 | 4.084200 | 18581 | 498 | 탕 찌개 전골 | mango |
61 | 슈발츠발트 | 4.1 | 27 | 4.083191 | 37976 | 972 | 카페 디저트 아메리카노 플랫 화이트 말차 프레 소 레몬 레이어 케이크 | mango |
63 | 이너프 | 4.1 | 23 | 4.081628 | 56636 | 1924 | 카페 디저트 | mango |
64 | 본가제일면가 | 4.1 | 23 | 4.081628 | 21333 | 552 | 국수 면 물 밀면 비빔면 회 밀면 곡 밀면 물 왕만두 알 | mango |
65 | 봉샌드 | 4.1 | 21 | 4.080732 | 18231 | 452 | 브런치 버거 샌드위치 | mango |
66 | 김유순대구뽈찜전문집 | 4.1 | 20 | 4.080250 | 7997 | 223 | 해산물 | mango |
67 | 기와집대구탕 | 4.1 | 18 | 4.079211 | 21836 | 536 | 해산물 | mango |
->Type 중에서 피자가 없기 때문에 이와 같은 화면이 출력된 것으로 판단된다
'Data Science > 여행 종합 추천 시스템 : 이지트립' 카테고리의 다른 글
[4] 프로젝트 후기 (0) | 2022.05.27 |
---|---|
[3] 사용한 코드 : CF-MF 추천시스템 (0) | 2022.05.27 |
[3] 사용한 코드 : 트립어드바이저 사이트 크롤링 (0) | 2022.05.27 |
[2] 데이터 수집, 정제, 모델링 (0) | 2022.05.27 |
[1] 주제 선정 (0) | 2022.05.27 |