본문 바로가기
Data Analysis

예제 5. 이디야는 스타벅스 근처에 위치한다 ?

by ram_ 2022. 11. 29.

Question

이디야 커피는 스타벅스 커피 매장이 위치하는 곳에 매장을 위치시킨다는 소문이 있다.

서울시의 이디야 커피와 스타벅스 커피 매장의 데이터를 분석하고 시각화하여 가설을 확인해보자.


Step 01.  스타벅스 웹크롤링

 

from selenium import webdriver
import pandas as pd
from urllib.request import urlopen
from bs4 import BeautifulSoup

req = driver.page_source
soup = BeautifulSoup(req, "html.parser")


url = "https://www.starbucks.co.kr/store/store_map.do?disp=locale"
driver = webdriver.Chrome("../driver/chromedriver")
driver.get(url)

# 서울 클릭
seoul = driver.find_element(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.click()
# 전체 클릭
wholeSeoul = driver.find_element(By.XPATH, '//*[@id="mCSB_2_container"]/ul/li[1]/a')
wholeSeoul.click()

stores = soup.select("#mCSB_3_container > ul > li")
stores[2].get

필요한 모듈을 불러온 뒤 chromedriver로 starbucks 페이지에 접근한다. xpath와 selector을 불러와 click()으로 자료에 접근한다.

 

# 매장이름, 주소, 구, 위도경도
import time
from tqdm import tqdm_notebook
starbucks_list = []

for store in tqdm_notebook(stores):
    
    name = store.find("strong").text
    address = store.find("p").text.replace("1522-3232", "")
    gu = address.split(" ")[1]
    lat = store["data-lat"]
    lng = store["data-long"]
    
    time.sleep(0.3)
    
    starbucks_list.append({
        "매장이름" : name,
        "주소" : address,
        "구" : gu,
        "위도" : lat,
        "경도" : lng
    })
   
starbucks = pd.DataFrame(starbucks_list)

# 저장
starbucks.to_csv("../ds_study/data/starbucks.csv", encoding="utf-8")

자료가 방대할거라 불러오는 내역을 보기 위해 tqdm을 불러온다. 매장 이름, 주소 등 불러오기 위해 태그들을 확인해준다. 

find().text로 문자열만 가져와 list로 만들어준다. 이후 그 리스트를 dataFrame으로 만들어준 뒤 저장한다.

 


Step 02.  이디야 웹크롤링

 

# 페이지 열기
url = "https://ediya.com/contents/find_store.html#c"
driver = webdriver.Chrome("../driver/chromedriver")
driver.get(url)

# 주소 탭 클릭
address_tab = driver.find_element(By.CSS_SELECTOR, '#contentWrap > div.contents > div > div.store_search_pop > ul > li:nth-child(2) > a')
address_tab.click()

이디야 페이지에 접속한다.

 

# 지역구를 하나하나 검색해 줄 수 없으니 , starbucks의 "구" 가져와서 검색

ediya_gu = list(starbucks["구"].unique())
ediya_list = []
tag = driver.find_element(By.XPATH, '//*[@id="keyword"]')

for gu in tqdm_notebook(ediya_gu):
    
    tag
    # 검색창 clear()
    tag.clear()
    # 검색창 입력
    tag.send_keys(f'서울 {gu}')
    # 검색 버튼 클릭 
    driver.find_element(By.XPATH, '//*[@id="keyword_div"]/form/button').click()
    
    # 정보 수집
    req = driver.page_source
    soup = BeautifulSoup(req, "html.parser")
    stores = soup.select("#placesList > li")
    
    time.sleep(0.5)

    # list
    for store in stores :
        name = store.select_one("dt").text
        address = store.select_one("dd").text
        gu = address.split(" ")[1]      
        ediya_list.append({
            "매장이름" : name,
            "주소" : address,
            "구" : gu
        })
        
driver.close()

ediya = pd.DataFrame(ediya_list)
ediya.head()

이디야 지점의 정보를 웹크롤링한다. 해당 구만 입력시에 정보가 너무 많다는 popup이 떠서 서울 ~구로 텍스트를 수정하였다. 

list에 정보들을 append 해준 뒤 driver.close()한다. 이를 DataFrame으로 만든다.

 

# 위도 경도 추가하기
import googlemaps
gmaps_key = "------<MY GMAPS KEY>-------"
gmaps = googlemaps.Client(key=gmaps_key)

import numpy as np

ediya["위도"] = np.nan
ediya["경도"] = np.nan

for idx, rows in tqdm_notebook(ediya.iterrows()):
    address = rows["주소"]
    tmp = gmaps.geocode(address, language="ko")
    
    if tmp : 
        lat = tmp[0].get("geometry")["location"]["lat"]
        lng = tmp[0].get("geometry")["location"]["lng"]
        ediya.loc[idx, "위도"] = lat
        ediya.loc[idx, "경도"] = lng
    else :
        print(idx, rows["주소"])

스타벅스애서는 경도와 위도가 자동적으로 추가되었는데, 이디야는 그렇지 않아 위차정보를 불러와주기 위해 gmaps.geocode로 이디야의 데이터프레임에 위도 경도를 추가해준다.

 

 


Step 03.  데이터 병합 및 시각화

 

# 브랜드 컬럼 추가
starbucks['브랜드'] = "starbucks"
ediya['브랜드'] = "ediya"

# 스타벅스 + 이디야 
df_sum = pd.concat([starbucks, ediya])
df_sum.reset_index(drop=True, inplace=True)

# 재설정
df_sum.reset_index(inplace=True)
del df_sum['index']

# nan값 처리
df_sum.dropna(inplace=True)
df_sum.info()

df_sum.to_csv('../ds_study/data/ediya_starbucks_sum.csv', encoding="utf-8")

두 데이터를 합칠텐데, 각 브랜드를 구분해주기 위해 브랜드 column을 추가해준다. 

pd.concat()을 사용해 두 데이터를 병합해준 뒤 index를 재설정 해준다. 

info를 확인해보니 nan값이 있어 dropna로 처리해준다. 원하는 위치에 저장해준다.

 

# 시각화
import folium
import json

mapping = folium.Map(location=[37.55021, 126.9824], zoom_start=11)

for idx, rows in df_sum.iterrows():
    
    # 브랜드 다르게 마커 설정
    if rows["브랜드"] =="starbucks":
        mk_color = "darkgreen"
        mk_icon = "star"
        iconColor="lightyellow"
        
        
    elif rows["브랜드"] == "ediya":
        mk_color = "blue"
        mk_icon = "coffee"
        iconColor="white"
        
    folium.Marker(
        location=[rows["위도"], rows["경도"]],
        popup = rows["주소"],
        tooltip = rows["매장이름"],
        icon = folium.Icon(
            icon = mk_icon , 
            prefix="fa",
            color= mk_color,
            icon_color = iconColor)
    ).add_to(mapping)

mapping

folium을 아용해 mapping해준다. 각 브랜드의 위치정보를 보고자 하여 브랜드 각각 다르게 표기해줬다.

서울시 안에 하도 많은 매장이 표시되다 보니 정작 알고 싶은 정보를 가져오기에는 어려움이 있어보였다.

도표를 그려 좀 더 알아보고자 했다.

import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import rc

plt.rcParams["axes.unicode_minus"] = False
rc("font", family = "Arial Unicode MS")
%matplotlib inline

# 구 별 매장 갯수
df_sum_cnt= df_sum.groupby(['구', '브랜드'])['매장이름'].count().reset_index(name='매장갯수')
df_sum_cnt.head()

# 구 별 매장 갯수 차이 시각화
plt.figure(figsize=(20, 6))
sns.barplot(x = df_sum_cnt['구'], y=df_sum_cnt['매장갯수'], data= df_sum_cnt, hue='브랜드', palette="Set3")
#plt.xticks(range(len(df_sum["구"].unique)), [starbucks["구"].unique()] )
plt.show()

각 구 별로 매장 갯수를 나누어 barplot을 만들어보았다. 갯수도 해당 가설을 확립시키기에는 마땅한 전제가 아니라고 생각하나,

내가 알 수 있는 데이터가 여기까지라 판단됐다. 


Step 04.  분석 결과

- 서울시의 스타벅스 매장 갯수 = 596, 이디야 매장 갯수 = 689개이다.
    - 강남구와 서초구, 종로구, 중구, 영등포구, 중량구를 뺀 나머지 구에는 이디야가 더 많이 존재한다.
    - 스타벅스 매장이 있는 곳에 이디야가 위치한다면, 두 브랜드의 매장 갯수는 구별로 편차가 적어야 한다고 생각한다.
      도봉구의 매장 갯수 차이나, 중량구에는 아예 이디야의 매장이 존재하지 않는 등 가설이 맞다고 하기에는 꺼림칙한 변수가 많다.

foliumMap애서 위치정보를 육안으로 확인해보니 서울 안의 웬만한 거리에는 스타벅스와 이디야 둘 다 위치한다.
유동인구가 많은 위치에 카페 지점을 냈을 뿐일텐데 왜 소비자는 이디야가 스타벅스 매장이 위치하는 곳에 매장을 위치시키는 것이 아니냐는 의심을 할까?

+ 사견

브랜드파워가 이유라고 판단된다. 스타벅스의 브랜드파워는 아주 강세하며 충성도가 높은 고객이 많다. 비슷한 위치에, 두 매장이 모두 존재한다면 비교적 존재감이 큰 스타벅스가 기준이 되어 이디야 커피가 따라서 위치할 것이라는 판단을 할 가능성이 있다.

 

+ 결론
매장 갯수와 위치만으로는 해당 가설을 확립시키기 부족하다.
각 브랜드 별 매장간의 거리, 어느 브랜드가 먼저 그곳에 지점을 냈는지 등 다른 변수들을 따져봐야 할 것이다.