728x90
반응형
1. 스타벅스 옆엔 이디야와 올리브영이 있다?
https://kid.chosun.com/site/data/html_dir/2022/06/02/2022060202963.html
프랜차이즈 브랜드 立地<입지> 선택의 법칙… 스타벅스 옆엔 이디야가 있다?
kid.chosun.com
2. 스타벅스 정보 크롤링
import time
import pandas as pd
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
def fetch_starbucks():
starbucks_url = 'https://www.starbucks.co.kr/index.do'
driver = webdriver.Chrome()
driver.maximize_window()
driver.get(starbucks_url)
time.sleep(1)
# ActionChains(): 마우스나 키보드와 같은 복잡한 사용자 상호작용을 시뮬레이션하는 데 사용
action = ActionChains(driver)
first_tag = driver.find_element(By.CSS_SELECTOR, '#gnb > div > nav > div > ul > li.gnb_nav03')
second_tag = driver.find_element(By.CSS_SELECTOR, '#gnb > div > nav > div > ul > li.gnb_nav03 > div > div > div > ul:nth-child(1) > li:nth-child(3) > a')
# perform(): ActionChains를 실행
action.move_to_element(first_tag).move_to_element(second_tag).click().perform()
seoul_tag = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable(
(By.CSS_SELECTOR, '#container > div > form > fieldset > div > section > article.find_store_cont > article > article:nth-child(4) > div.loca_step1 > div.loca_step1_cont > ul > li:nth-child(1) > a')
))
seoul_tag.click()
# 매장정보를 담기 위한 빈 리스트
store_list = []
addr_list = []
lat_list = []
lng_list = []
WebDriverWait(driver, 5).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'set_gugun_cd_btn')))
gu_elements = driver.find_elements(By.CLASS_NAME, 'set_gugun_cd_btn')
WebDriverWait(driver, 5).until(
EC.element_to_be_clickable(
(By.CSS_SELECTOR, '#mCSB_2_container > ul > li:nth-child(1) > a')
))
gu_elements[0].click()
WebDriverWait(driver, 5).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'quickResultLstCon')))
req = driver.page_source
soup = BeautifulSoup(req)
stores = soup.find('ul', 'quickSearchResultBoxSidoGugun').find_all('li')
for store in stores:
store_name = store.find('strong').text
store_addr = store.find('p').text
store_addr = re.sub(r'\d{4}-\d{4}$', '', store_addr).strip()
store_lat = store['data-lat']
store_lng = store['data-long']
store_list.append(store_name)
addr_list.append(store_addr)
lat_list.append(store_lat)
lng_list.append(store_lng)
df = pd.DataFrame({
'store': store_list,
'addr': addr_list,
'lat': lat_list,
'lng': lng_list
})
driver.quit()
return df
starbucks_df = fetch_starbucks()
starbucks_df.to_csv('starbucks_seoul.csv', index=False, encoding='utf-8-sig')
print("데이터가 starbucks_seoul.csv 파일로 저장되었습니다.")
3. 데이터 전처리
import pandas as pd
df_starbugs = pd.read_csv('/본인의 구글드라이브 경로/starbucks_seoul.csv')
df_starbugs
df_starbugs = df_starbugs.set_axis(['지점명', '지점주소', '지점위도', '지점경도'], axis=1).reset_index(drop=True)
df_starbugs
df = pd.read_csv('/본인의 구글드라이브 경로/소상공인시장진흥공단_상가(상권)정보_서울_202409.csv', low_memory=False)
df
df.info()
shop = ['이디야', '올리브영', '컴포즈커피', '빽다방', '메가커피', '메가엠지씨']
# 메가커피(메가엠지씨) 데이터 필터링
# contains(): 특정 문자열 포함 여부에 따라 True, False를 반환
# case=False: 대소문자를 구분하지 않겠다는 설정
# na=False: 결측치(NaN) 처리. 결측치가 있는 경우 False로 간주하여 결과에 포함되지 않음
df[df["상호명"].str.contains("메가엠지씨", case=False, na=False)]
df[df["상호명"].str.contains("메가커피", case=False, na=False)]
df[df["상호명"].str.contains('메가커피|메가엠지씨', case=False, na=False)]
df_shop = df.copy()
# shop = ['이디야', '올리브영', '컴포즈커피', '빽다방', '메가커피', '메가엠지씨']
# 이디야|올리브영|컴포즈커피|빽다방|메가커피|메가엠지씨
# extract(): 특정 문자열을 포함하고 있으면 그 문자열을 반환하고, 포함하지 않으면 NaN을 반환
df_shop['상호명'] = df_shop['상호명'].str.extract('({})'.format('|'.join(shop)))
df_shop['상호명']
df_shop = df_shop.dropna(subset=['상호명']).iloc[:, [0, 1, 14, 37, 38]].reset_index(drop=True)
df_shop
# 상호명에서 "메가엠지씨"를 "메가커피"로 변경
df_shop['상호명'] = df_shop['상호명'].str.replace('메가엠지씨', '메가커피', regex=False)
df_shop
df_shop[df_shop['상호명'].str.contains('메가엠지씨', na=False)]
print(df_shop.shape)
print(df_starbugs.shape)
df_cross = df_shop.merge(df_starbugs, how='cross')
df_cross
4. 하버사인 공식
Haversine 공식은 구체(구면) 위의 두 점(위도와 경도로 표시됨) 사이의 최단 거리(대원 거리, great-circle distance)를 계산하는 방법입니다. 이 공식은 GPS 좌표(위도와 경도)를 활용하여 지구 표면 위의 거리 계산에 널리 사용됩니다.
from haversine import haversine
df_cross['거리'] = df_cross.apply(lambda x: haversine([x['위도'], x['경도']], [x['지점위도'], x['지점경도']], unit='m'), axis=1)
df_cross
# 개별 커피 매장과 스타벅스와의 최소 거리
df_dis = df_cross.groupby(['상호명'])['거리'].min().reset_index()
df_dis
# 각 프렌차이즈 별 스타벅스와의 평균 거리
df_dis.groupby('상호명')['거리'].mean()
# agg(): 다중 집계작업을 간단하게 해주는 함수
df_dis.groupby('상호명')['거리'].agg(['mean', 'count'])
# 거리를 입력하면 프렌차이즈 별 스타벅스와의 평균거리와 매장개수를 출력하는 함수
def distance(x):
dis = df_dis['거리'] <= x
return df_dis[dis].groupby('상호명')['거리'].agg(['mean', 'count'])
distance(100)
5. 차트 시각화
!pip install pandasecharts
df_100 = distance(100).reset_index()
df_100
import IPython
from pandasecharts import echart
df_100.echart.pie(x='상호명', y='count', figsize=(600, 400),
radius=['20%', '60%'], label_opts={'position':'outer'},
title='커피 프렌차이즈의 입점전략은 과연 스타벅스 옆인가?',
legend_opts={'pos_right':'0%', 'orient':'vertical'},
subtitle='100m 이내 매장수', init_opts={'bg_color': 'white'}).render()
IPython.display.HTML(filename='render.html')
from pyecharts.charts import Timeline, Grid
tl = Timeline({'width':'600px', 'height':'400px'})
for i in [1000, 100, 50, 30]:
df_d = distance(i).reset_index()
pie1 = df_d.echart.pie(x='상호명', y='count', figsize=(600, 400),
radius=['20%', '60%'], label_opts={'position':'outer'},
title='커피 프렌차이즈의 입점전략은 과연 스타벅스 옆인가?',
legend_opts={'pos_right':'0%', 'orient':'vertical'},
subtitle='{}m 이내 매장수'.format(i), init_opts={'bg_color': 'white'})
tl.add(pie1, '{}m'.format(i)).render()
IPython.display.HTML(filename='render.html')
728x90
반응형
'인공지능 > 데이터분석' 카테고리의 다른 글
사이킷런 (0) | 2024.12.31 |
---|---|
머신러닝과 딥러닝 (3) | 2024.12.23 |
서울시 공공자전거 실시간 대여정보 (2) | 2024.12.19 |
소상공인시장진흥공단_상가정보 데이터셋 (2) | 2024.12.18 |
Online Retail 데이터셋 살펴보기 (1) | 2024.12.15 |