서울시 스타벅스 매장 입점 관계

Nunucoder·2021년 7월 26일
0
post-thumbnail

'중심상가'라 칭하는곳에 가보면 스타벅스가 근처에 여러 매장들이 존재한다.

동네에는 잘 입점하지 않고 사람들의 유동이 많은곳에 스타벅스가 주로 있는거 같다는 의문이 들었다.

여러 요인들이 있겠지만 포괄적인 요인을 대강 알아보기위해 서울시에서 스타벅스의 매장 입점 관계를 알아보기 위해 분석을 했다.

'직장인을 위한 파이썬 데이터분석' 을 이용하였으며 거기서 나오는 기법들을 사용했다.

다음에는 경기 남부를 기준으로 한번 더 해볼예정이다.

from selenium import webdriver 
from bs4 import BeautifulSoup
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import matplotlib as mpl
%matplotlib inline

mpl.rcParams['axes.unicode_minus'] = False
path = 'C:/Users/leez/NanumBarunGothic.ttf'
font_name = fm.FontProperties(fname=path, size=50).get_name()
print(font_name)
plt.rc('font', family=font_name)
plt.rcParams["font.size"] = 15
plt.rcParams["figure.figsize"] = (8,5)
NanumBarunGothic

STEP 1 . 데이터 가져오기

1. selenium 과 beautifulsoup을 이용한 웹크롤링

browser = webdriver.Chrome("c:/playwithdata/chromedriver.exe")
url = 'https://www.starbucks.co.kr/store/store_map.do?disp=locale'
browser.get(url)

html 위치 가져오기

  • 도구더보기 >> 개발자도구 >> 네모 화살표 클릭후 >> 해당 위치를 누르면 정보가 나옴 >> 우클릭 copy select
seoul_btn ='#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'
browser.find_element_by_css_selector(seoul_btn).click() # 서울 매장 클릭
all_btn = '#mCSB_2_container > ul > li:nth-child(1) > a'
browser.find_element_by_css_selector(all_btn).click()
html = browser.page_source # 크롬 브라우저에 현재 화면에 나타난 웹페이지의 html을 가져옴
soup = BeautifulSoup(html,'html.parser') # 'html.parser' 는 html 문법을 이해하고 웹페이지 정보를 분류
starbucks_soup_list = soup.select('li.quickResultLstCon')
print(len(starbucks_soup_list))
556
starbucks_soup_list[0]
<li class="quickResultLstCon" data-code="3762" data-hlytag="null" data-index="0" data-lat="37.501087" data-long="127.043069" data-name="역삼아레나빌딩" data-storecd="1509" style="background:#fff"> <strong data-my_siren_order_store_yn="N" data-name="역삼아레나빌딩" data-store="1509" data-yn="N">역삼아레나빌딩  </strong> <p class="result_details">서울특별시 강남구 언주로 425 (역삼동)<br/>1522-3232</p> <i class="pin_general">리저브 매장 2번</i></li>
  • data-lat = 위도
  • data-long = 경도
starbucks_store = starbucks_soup_list[0]
name = starbucks_store.select('strong')[0].text.strip()
lat= starbucks_store['data-lat'].strip()
lng= starbucks_store['data-long'].strip()
store_type = starbucks_store.select('i')[0]['class'][0][4:]
address = str(starbucks_store.select('p.result_details')[0]).split('<br/')[0].split('>')[1]
tel=str(starbucks_store.select('p.result_details')[0]).split('<br/>')[1].split('<')[0]
              
print(name)
print(lat)
print(lng)
print(store_type)
print(address)
print(tel)
역삼아레나빌딩
37.501087
127.043069
general
서울특별시 강남구 언주로 425 (역삼동)
1522-3232
some = str(starbucks_store.select('p.result_details')[0])
print(some)
some = str(starbucks_store.select('p.result_details')[0]).split('<br/')[0]
print(some)
some =str(starbucks_store.select('p.result_details')[0]).split('<br/')[0].split('>')[1]
print(some)
<p class="result_details">서울특별시 강남구 언주로 425 (역삼동)<br/>1522-3232</p>
<p class="result_details">서울특별시 강남구 언주로 425 (역삼동)
서울특별시 강남구 언주로 425 (역삼동)
  1. p class를 str을 이용해 문자열로 바꿔줌

  2. split('<br/') 를 이용해 리스트의 항목으로 나눠줌

  3. split('>')를 한번더해 리스트 항목을 더 만들고 그중에 [1]을 가져온것이 주소

서울의 각 매장을 csv로 변경

starbucks_list =[]
for item in starbucks_soup_list:
    name = item.select('strong')[0].text.strip()
    lat= item['data-lat'].strip()
    lng= item['data-long'].strip()
    store_type = item.select('i')[0]['class'][0][4:]
    address = str(item.select('p.result_details')[0]).split('<br/')[0].split('>')[1]
    tel=str(item.select('p.result_details')[0]).split('<br/>')[1].split('<')[0]
    
    starbucks_list.append([name,lat,lng,store_type,address,tel])
columns =['매장명','위도','경도','매장타입','주소','전화번호']
seoul_starbucks_df = pd.DataFrame(starbucks_list,columns=columns)
seoul_starbucks_df.head() 
매장명 위도 경도 매장타입 주소 전화번호
0 역삼아레나빌딩 37.501087 127.043069 general 서울특별시 강남구 언주로 425 (역삼동) 1522-3232
1 논현역사거리 37.510178 127.022223 general 서울특별시 강남구 강남대로 538 (논현동) 1522-3232
2 신사역성일빌딩 37.514132 127.020563 general 서울특별시 강남구 강남대로 584 (논현동) 1522-3232
3 국기원사거리 37.499517 127.031495 general 서울특별시 강남구 테헤란로 125 (역삼동) 1522-3232
4 스탈릿대치R 37.494668 127.062583 reserve 서울특별시 강남구 남부순환로 2947 (대치동) 1522-3232
seoul_starbucks_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 556 entries, 0 to 555
Data columns (total 6 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   매장명     556 non-null    object
 1   위도      556 non-null    object
 2   경도      556 non-null    object
 3   매장타입    556 non-null    object
 4   주소      556 non-null    object
 5   전화번호    556 non-null    object
dtypes: object(6)
memory usage: 26.2+ KB
seoul_starbucks_df.to_csv('C:\playwithdata\starbuck_in_seoul.csv',encoding='cp949')

STEP2 . 데이터 추가

  • 서울시 구별 위도,경도 데이터
  • 서울시 구별 주민등록인구수
  • 서울시 구별 사업체(직장) 현황

위 세개 데이터를 추가했다.

각 서울시 구별 위도 경도 데이터

total_seoul_loc = pd.read_csv(r'C:\playwithdata\스타벅스\서울시행정구역정보.csv',encoding='cp949')
total_seoul_loc = total_seoul_loc.drop(['순번','시군구명_영문','ESRI_PK'],axis=1)
total_seoul_loc 
시군구코드 시군구명 위도 경도
0 11320 도봉구 37.665861 127.031767
1 11380 은평구 37.617612 126.922700
2 11230 동대문구 37.583801 127.050700
3 11590 동작구 37.496504 126.944307
4 11545 금천구 37.460097 126.900155
5 11530 구로구 37.495486 126.858121
6 11110 종로구 37.599100 126.986149
7 11305 강북구 37.646995 127.014716
8 11260 중랑구 37.595379 127.093967
9 11680 강남구 37.495985 127.066409
10 11500 강서구 37.565762 126.822656
11 11140 중구 37.557945 126.994190
12 11740 강동구 37.549208 127.146482
13 11215 광진구 37.548144 127.085753
14 11440 마포구 37.562291 126.908780
15 11650 서초구 37.476953 127.037810
16 11290 성북구 37.606991 127.023218
17 11350 노원구 37.655264 127.077120
18 11710 송파구 37.504853 127.114482
19 11410 서대문구 37.582037 126.935667
20 11470 양천구 37.527062 126.856153
21 11560 영등포구 37.520641 126.913924
22 11620 관악구 37.465399 126.943807
23 11200 성동구 37.550675 127.040962
24 11170 용산구 37.531101 126.981074

서울시 주민등록상 인구

sgg_pop_df = pd.read_csv(r'C:\playwithdata\스타벅스\주민등록인원수.txt',sep='\t',header=2)
sgg_pop_df
기간 자치구 세대 남자 여자 계.1 남자.1 여자.1 계.2 남자.2 여자.2 세대당인구 65세이상고령자
0 2021.1/4 합계 4,400,403 9,828,094 4,774,856 5,053,238 9,598,484 4,667,524 4,930,960 229,610 107,332 122,278 2.18 1,567,819
1 2021.1/4 종로구 74,113 156,567 75,772 80,795 147,296 71,644 75,652 9,271 4,128 5,143 1.99 27,781
2 2021.1/4 중구 63,746 133,708 65,312 68,396 124,552 60,851 63,701 9,156 4,461 4,695 1.95 24,767
3 2021.1/4 용산구 112,881 243,336 118,120 125,216 229,013 110,181 118,832 14,323 7,939 6,384 2.03 39,575
4 2021.1/4 성동구 135,883 298,421 145,358 153,063 291,906 142,506 149,400 6,515 2,852 3,663 2.15 45,968
5 2021.1/4 광진구 166,638 356,191 171,131 185,060 343,392 165,747 177,645 12,799 5,384 7,415 2.06 50,370
6 2021.1/4 동대문구 165,924 352,570 173,309 179,261 338,875 167,895 170,980 13,695 5,414 8,281 2.04 60,868
7 2021.1/4 중랑구 185,506 396,807 195,639 201,168 392,041 193,752 198,289 4,766 1,887 2,879 2.11 69,841
8 2021.1/4 성북구 193,965 444,295 213,586 230,709 434,826 209,902 224,924 9,469 3,684 5,785 2.24 73,158
9 2021.1/4 강북구 144,410 307,537 149,582 157,955 304,078 148,306 155,772 3,459 1,276 2,183 2.11 62,893
10 2021.1/4 도봉구 138,120 323,752 157,562 166,190 321,717 156,810 164,907 2,035 752 1,283 2.33 62,360
11 2021.1/4 노원구 217,272 522,225 251,719 270,506 518,278 249,942 268,336 3,947 1,777 2,170 2.39 85,906
12 2021.1/4 은평구 212,725 479,607 229,589 250,018 475,501 227,910 247,591 4,106 1,679 2,427 2.24 85,140
13 2021.1/4 서대문구 143,180 318,814 151,331 167,483 308,482 147,655 160,827 10,332 3,676 6,656 2.15 53,440
14 2021.1/4 마포구 177,170 378,216 177,377 200,839 368,518 173,624 194,894 9,698 3,753 5,945 2.08 53,494
15 2021.1/4 양천구 180,682 456,019 223,450 232,569 452,677 222,010 230,667 3,342 1,440 1,902 2.51 66,231
16 2021.1/4 강서구 267,442 582,804 280,942 301,862 577,320 278,444 298,876 5,484 2,498 2,986 2.16 89,377
17 2021.1/4 구로구 180,027 426,675 212,092 214,583 401,074 198,034 203,040 25,601 14,058 11,543 2.23 70,717
18 2021.1/4 금천구 114,402 244,564 124,300 120,264 229,844 116,322 113,522 14,720 7,978 6,742 2.01 39,781
19 2021.1/4 영등포구 184,133 403,070 200,380 202,690 377,590 186,692 190,898 25,480 13,688 11,792 2.05 61,197
20 2021.1/4 동작구 183,579 398,205 192,187 206,018 388,730 188,045 200,685 9,475 4,142 5,333 2.12 65,396
21 2021.1/4 관악구 273,736 504,140 252,400 251,740 490,352 246,097 244,255 13,788 6,303 7,485 1.79 78,400
22 2021.1/4 서초구 172,181 425,103 203,489 221,614 421,315 201,619 219,696 3,788 1,870 1,918 2.45 60,209
23 2021.1/4 강남구 233,363 539,538 258,205 281,333 534,796 255,880 278,916 4,742 2,325 2,417 2.29 75,602
24 2021.1/4 송파구 280,237 667,115 321,658 345,457 661,411 319,047 342,364 5,704 2,611 3,093 2.36 94,145
25 2021.1/4 강동구 199,088 468,815 230,366 238,449 464,900 228,609 236,291 3,915 1,757 2,158 2.34 71,203
ssg_pop_df_final =sgg_pop_df[['자치구','계']][1:]
ssg_pop_df_final.head()
자치구
1 종로구 156,567
2 중구 133,708
3 용산구 243,336
4 성동구 298,421
5 광진구 356,191
ssg_pop_df_final.columns = ['시군구명','주민등록인구']
ssg_pop_df_final.head()
시군구명 주민등록인구
1 종로구 156,567
2 중구 133,708
3 용산구 243,336
4 성동구 298,421
5 광진구 356,191

서울시 사업체 데이터

ssg_biz_df = pd.read_csv(r'C:\playwithdata\스타벅스\사업체현황.txt',sep='\t',header=1)
ssg_biz_df= ssg_biz_df[['자치구','동','종사자수','사업체수',]]
ssg_biz_df['동'].astype(str)
0         동
1        합계
2        소계
3       사직동
4       삼청동
       ... 
446    둔촌1동
447    둔촌2동
448    암사1동
449    천호2동
450      길동
Name: 동, Length: 451, dtype: object
ssg_biz_df= ssg_biz_df[ssg_biz_df['동']=='소계'].reset_index()
ssg_biz_df.drop(['동','index'],axis=1,inplace=True)
ssg_biz_df.columns = ['시군구명','종사자수','사업체수']

서울시 스타벅스/구별 위도,경도/주민등록인구수/사업체수 병합

seoul_starbucks=pd.read_csv('C:\playwithdata\starbuck_in_seoul.csv',encoding='cp949',index_col=0)
seoul_starbucks.head()
매장명 위도 경도 매장타입 주소 전화번호
0 역삼아레나빌딩 37.501087 127.043069 general 서울특별시 강남구 언주로 425 (역삼동) 1522-3232
1 논현역사거리 37.510178 127.022223 general 서울특별시 강남구 강남대로 538 (논현동) 1522-3232
2 신사역성일빌딩 37.514132 127.020563 general 서울특별시 강남구 강남대로 584 (논현동) 1522-3232
3 국기원사거리 37.499517 127.031495 general 서울특별시 강남구 테헤란로 125 (역삼동) 1522-3232
4 스탈릿대치R 37.494668 127.062583 reserve 서울특별시 강남구 남부순환로 2947 (대치동) 1522-3232
ssg_name = []
for i in seoul_starbucks['주소']:
    ssg = i.split()[1]
    ssg_name.append(ssg)
seoul_starbucks['시군구명']=ssg_name
seoul_starbucks
매장명 위도 경도 매장타입 주소 전화번호 시군구명
0 역삼아레나빌딩 37.501087 127.043069 general 서울특별시 강남구 언주로 425 (역삼동) 1522-3232 강남구
1 논현역사거리 37.510178 127.022223 general 서울특별시 강남구 강남대로 538 (논현동) 1522-3232 강남구
2 신사역성일빌딩 37.514132 127.020563 general 서울특별시 강남구 강남대로 584 (논현동) 1522-3232 강남구
3 국기원사거리 37.499517 127.031495 general 서울특별시 강남구 테헤란로 125 (역삼동) 1522-3232 강남구
4 스탈릿대치R 37.494668 127.062583 reserve 서울특별시 강남구 남부순환로 2947 (대치동) 1522-3232 강남구
... ... ... ... ... ... ... ...
551 사가정역 37.579594 127.087966 general 서울특별시 중랑구 면목로 310 1522-3232 중랑구
552 상봉역 37.596890 127.086470 general 서울특별시 중랑구 망우로 307 (상봉동) 1522-3232 중랑구
553 묵동이마트 37.613433 127.077484 general 서울특별시 중랑구 동일로 932 (묵동, 묵동자이아파트) (묵동이마트 B1층) 1522-3232 중랑구
554 묵동 37.615368 127.076633 general 서울특별시 중랑구 동일로 952 1522-3232 중랑구
555 중화역 37.601709 127.078411 general 서울특별시 중랑구 봉화산로 35 1,2층 1522-3232 중랑구

556 rows × 7 columns

위 파일 변수명

  • 위도 경도 : total_seoul_loc

  • 주민등록인구 : ssg_pop_df_final

  • 사업체수 :ssg_biz_df

seoul_starbucks_count = seoul_starbucks.pivot_table(index='시군구명',values='매장명',aggfunc='count').rename(columns={'매장명':'스타벅스_매장수'})
seoul_starbucks_count
스타벅스_매장수
시군구명
강남구 85
강동구 15
강북구 5
강서구 19
관악구 11
광진구 17
구로구 11
금천구 11
노원구 13
도봉구 3
동대문구 9
동작구 11
마포구 32
서대문구 20
서초구 48
성동구 11
성북구 14
송파구 33
양천구 17
영등포구 38
용산구 21
은평구 8
종로구 40
중구 56
중랑구 8
seoul_sgg = pd.merge(total_seoul_loc,seoul_starbucks_count,how='left',on='시군구명')
seoul_sgg =pd.merge(seoul_sgg,ssg_pop_df_final,how='left',on='시군구명')
seoul_sgg =pd.merge(seoul_sgg,ssg_biz_df,how='left',on='시군구명')
seoul_sgg
시군구코드 시군구명 위도 경도 스타벅스_매장수 주민등록인구 종사자수 사업체수
0 11320 도봉구 37.665861 127.031767 3 323,752 72,939 18,628
1 11380 은평구 37.617612 126.922700 8 479,607 93,631 24,681
2 11230 동대문구 37.583801 127.050700 9 352,570 138,400 31,324
3 11590 동작구 37.496504 126.944307 11 398,205 106,159 19,793
4 11545 금천구 37.460097 126.900155 11 244,564 242,686 33,814
5 11530 구로구 37.495486 126.858121 11 426,675 225,668 38,756
6 11110 종로구 37.599100 126.986149 40 156,567 260,446 39,679
7 11305 강북구 37.646995 127.014716 5 307,537 73,904 19,014
8 11260 중랑구 37.595379 127.093967 8 396,807 103,345 28,228
9 11680 강남구 37.495985 127.066409 85 539,538 698,840 71,027
10 11500 강서구 37.565762 126.822656 19 582,804 257,494 39,458
11 11140 중구 37.557945 126.994190 56 133,708 392,568 60,127
12 11740 강동구 37.549208 127.146482 15 468,815 141,770 29,080
13 11215 광진구 37.548144 127.085753 17 356,191 126,305 24,445
14 11440 마포구 37.562291 126.908780 32 378,216 247,276 37,290
15 11650 서초구 37.476953 127.037810 48 425,103 438,985 46,940
16 11290 성북구 37.606991 127.023218 14 444,295 111,005 23,617
17 11350 노원구 37.655264 127.077120 13 522,225 116,684 26,618
18 11710 송파구 37.504853 127.114482 33 667,115 341,201 48,644
19 11410 서대문구 37.582037 126.935667 20 318,814 113,819 20,095
20 11470 양천구 37.527062 126.856153 17 456,019 121,582 25,894
21 11560 영등포구 37.520641 126.913924 38 403,070 373,478 42,370
22 11620 관악구 37.465399 126.943807 11 504,140 115,329 25,505
23 11200 성동구 37.550675 127.040962 11 298,421 178,243 28,343
24 11170 용산구 37.531101 126.981074 21 243,336 135,240 20,254
seoul_sgg.to_csv('C:\playwithdata\seoul_sgg.csv',encoding='cp949')

STEP3. 데이터 시각화

folium을 이용하여 각 지점들을 지도위에 표현했다.

import folium # 데이터를 지도위에 표현함
seoul_starbucks = pd.read_csv('C:\playwithdata\starbuck_in_seoul.csv',encoding='cp949',index_col=0)
seoul_starbucks.head()
매장명 위도 경도 매장타입 주소 전화번호
0 역삼아레나빌딩 37.501087 127.043069 general 서울특별시 강남구 언주로 425 (역삼동) 1522-3232
1 논현역사거리 37.510178 127.022223 general 서울특별시 강남구 강남대로 538 (논현동) 1522-3232
2 신사역성일빌딩 37.514132 127.020563 general 서울특별시 강남구 강남대로 584 (논현동) 1522-3232
3 국기원사거리 37.499517 127.031495 general 서울특별시 강남구 테헤란로 125 (역삼동) 1522-3232
4 스탈릿대치R 37.494668 127.062583 reserve 서울특별시 강남구 남부순환로 2947 (대치동) 1522-3232
starbucks_map = folium.Map(
    location = [37.573050,126.979189],
    tiles = 'Stamen Terrain',
    zoom_start=11
)
starbucks_map

folium에 매장표시

for idx in seoul_starbucks.index:
    lat =seoul_starbucks.loc[idx,'위도']
    lng =seoul_starbucks.loc[idx,'경도']
    
    folium.CircleMarker(
        location=[lat,lng],
        fill =True,
        fill_color = 'green',
        fill_opacity =1,
        color = 'yellow',
        weight=1,
        radius=3,
    ).add_to(starbucks_map)
    
starbucks_map 

강남구와 종로구에 스타벅스매장의 수가 많은것을 확인할수 있다.

매장 특징별 분포 확인

starbucks_map2 = folium.Map(
    location = [37.573050,126.979189],
    tiles = 'Stamen Terrain',
    zoom_start=11
)

for idx in seoul_starbucks.index:
    lat =seoul_starbucks.loc[idx,'위도']
    lng =seoul_starbucks.loc[idx,'경도']
    store_type = seoul_starbucks.loc[idx,'매장타입']
    
    fillColor=''
    if store_type == 'general':
        fillColor = 'black'
        size =1
    elif store_type == 'reserve':
        fillColor = 'blue'
        size =5
    elif store_type == 'generalDT':
        fillColor = 'red'
        size =5
        
    
    folium.CircleMarker(
        location=[lat,lng],
        color = fillColor,
        fill =True,
        fill_color = fillColor,
        fill_opacity =1,
        weight=1,
        radius=size
    ).add_to(starbucks_map2)

starbucks_map2

서울시 스타벅스 매장의 특징

  • 드라이브스루 :빨강

  • 리저브 : 파랑

  • 일반매장 : 검정

서울 외곽에 드라이브 스루 매장이 많이 분포되어있고 ,강남과 종로에는 리저브 매장이 많이 분포되있는걸 확인할수있다.

시군구별 스타벅스 매장수 시각화

import json
seoul_sgg_stat = pd.read_csv('C:\playwithdata\seoul_sgg.csv',encoding='cp949',index_col=0)
seoul_sgg_stat.head()
시군구코드 시군구명 위도 경도 스타벅스_매장수 주민등록인구 종사자수 사업체수
0 11320 도봉구 37.665861 127.031767 3 323,752 72,939 18,628
1 11380 은평구 37.617612 126.922700 8 479,607 93,631 24,681
2 11230 동대문구 37.583801 127.050700 9 352,570 138,400 31,324
3 11590 동작구 37.496504 126.944307 11 398,205 106,159 19,793
4 11545 금천구 37.460097 126.900155 11 244,564 242,686 33,814
ssg_geojson_file_path ='C:\playwithdata\스타벅스\seoul_sgg.geojson'
seoul_sgg_geo = json.load(open(ssg_geojson_file_path,encoding='utf=8'))
seoul_sgg_geo['features'][0]['properties']
{'SIG_CD': '11320',
 'SIG_KOR_NM': '도봉구',
 'SIG_ENG_NM': 'Dobong-gu',
 'ESRI_PK': 0,
 'SHAPE_AREA': 0.00210990544544,
 'SHAPE_LEN': 0.239901251347}
starbucks_bubble = folium.Map(
    location=[37.573050,126.979189],
    tiles = 'CartoDB dark_matter', #배경지도 할당 
    zoom_start=11
)
def style_function(feature):
    return {
        'opacity' :0.7,
        'weight' : 1,
        'color':'white',
        'fillOpacity':0,
        'dashArray':'5,5',
    }

folium.GeoJson(
    seoul_sgg_geo,
    style_function = style_function
).add_to(starbucks_bubble)

starbucks_bubble

starbucks_mean = seoul_sgg_stat['스타벅스_매장수'].mean()
print(starbucks_mean)
22.24
for idx in seoul_sgg_stat.index:
    lat = seoul_sgg_stat.loc[idx, '위도']
    lng = seoul_sgg_stat.loc[idx, '경도']
    count = seoul_sgg_stat.loc[idx, '스타벅스_매장수']

    if count > starbucks_mean:
        fillColor = 'red'
    else:
        fillColor = 'blue'
    
    folium.CircleMarker(
        location=[lat, lng], 
        color='grey',
        fill_color=fillColor, 
        fill_opacity=0.7,
        weight=1.5,
        radius=count/2
    ).add_to(starbucks_bubble)

starbucks_bubble

시군구별 평균보다 매장수가 많은곳은 빨간색으로 적은곳은 파란색으로 나타냈다.

ssg_geojson_file_path ='C:\playwithdata\스타벅스\seoul_sgg.geojson'
seoul_sgg_geo_2 = json.load(open(ssg_geojson_file_path,encoding='utf=8'))
starbucks_choropleth = folium.Map(
    location=[37.573050,126.979189],
    tiles = 'CartoDB dark_matter', #배경지도 할당 
    zoom_start=11
)

folium.Choropleth(
    geo_data=seoul_sgg_geo_2,
    data=seoul_sgg_stat,
    columns=['시군구명', '스타벅스_매장수'],
    fill_color = 'YlGn',
    fill_opacity=0.7,
    line_opacity=0.5,
    key_on='properties.SIG_KOR_NM'
    ).add_to(starbucks_choropleth)

starbucks_choropleth

단계구분도(folium.Choropleth)를 이용한 시각화

geo_data : 지도 데이터를 지정

data : 데이터프레임 데이터를 지정

** columns : 두개의 값을 리스트로 넣어준다 . 첫번째값은 지도와 매칭되는 값(SIG_KOR_NM == 시군구명) , 두번째값은 value로 단계구분을 지정할 정수값

key_on : 'properties.SIG_KOR_NM'를 입력해 '시군구명' 칼럼과 매칭

STEP 4. 스타벅스 입지지점과 관계 특징 찾기

1. 스타벅스 매장수와 인구수 비교

가정 : 거주인원이 많은 지역에 스타벅스 매장이 많이 입지해 있을것이다.

seoul_sgg_stat = pd.read_csv('C:\playwithdata\seoul_sgg.csv',encoding='cp949',index_col=0)
seoul_sgg_stat.head()
시군구코드 시군구명 위도 경도 스타벅스_매장수 주민등록인구 종사자수 사업체수
0 11320 도봉구 37.665861 127.031767 3 323,752 72,939 18,628
1 11380 은평구 37.617612 126.922700 8 479,607 93,631 24,681
2 11230 동대문구 37.583801 127.050700 9 352,570 138,400 31,324
3 11590 동작구 37.496504 126.944307 11 398,205 106,159 19,793
4 11545 금천구 37.460097 126.900155 11 244,564 242,686 33,814
def value_chanes(name): # 문자열을 float형으로 바꿔주기위해 설정함
    for i in range(len(seoul_sgg_stat[name])):
        seoul_sgg_stat[name][i] = seoul_sgg_stat[name][i].replace(',',"")
    
    seoul_sgg_stat[name] = seoul_sgg_stat[name].astype(float)
value_chanes('주민등록인구')
value_chanes('종사자수')
value_chanes('사업체수');
<ipython-input-61-cc989170fbfb>:3: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  seoul_sgg_stat[name][i] = seoul_sgg_stat[name][i].replace(',',"")
seoul_sgg_stat.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 25 entries, 0 to 24
Data columns (total 8 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   시군구코드     25 non-null     int64  
 1   시군구명      25 non-null     object 
 2   위도        25 non-null     float64
 3   경도        25 non-null     float64
 4   스타벅스_매장수  25 non-null     int64  
 5   주민등록인구    25 non-null     float64
 6   종사자수      25 non-null     float64
 7   사업체수      25 non-null     float64
dtypes: float64(5), int64(2), object(1)
memory usage: 2.4+ KB
ssg_geojson_file_path ='C:\playwithdata\스타벅스\seoul_sgg.geojson'
seoul_sgg_geo = json.load(open(ssg_geojson_file_path,encoding='utf=8'))
starbucks_choropleth = folium.Map(
    location=[37.573050,126.979189],
    tiles = 'CartoDB dark_matter', #배경지도 할당 
    min_zoom = 10,
    max_zoom =12,
    zoom_start=11
)

folium.Choropleth(
    geo_data=seoul_sgg_geo_2,
    data=seoul_sgg_stat,
    columns=['시군구명', '주민등록인구'],
    fill_color = 'YlGn',
    fill_opacity=0.7,
    line_opacity=0.5,
    key_on='properties.SIG_KOR_NM'
    ).add_to(starbucks_choropleth)

starbucks_choropleth

seoul_sgg_stat_sort = seoul_sgg_stat.sort_values(['주민등록인구'],ascending=False)
plt.figure(figsize=(22,5))

plt.bar(seoul_sgg_stat_sort['시군구명'],seoul_sgg_stat_sort['주민등록인구'],color='green')
plt.title('서울시 구별 주민등록인구수 ', fontsize=20)
plt.xlabel('시군구명', fontsize=18)
plt.ylabel('주민등록인구', fontsize=18)
plt.show()

주민등록 인구수는 송파구 >> 강서구 >> 강남구 순으로 확인

인구수 대비 스타벅스 매장수 확인

seoul_sgg_stat['만명당_매장수'] = seoul_sgg_stat['스타벅스_매장수']/(seoul_sgg_stat['주민등록인구']/10000)
SGG_GEOJSON_FILE_PATH = 'C:\playwithdata\스타벅스\seoul_sgg.geojson'
seoul_sgg_geo_1 = json.load(open(SGG_GEOJSON_FILE_PATH, encoding='utf-8'))

viz_map_1 = folium.Map(
    location=[37.573050, 126.979189],
    tiles='CartoDB dark_matter',
    zoom_start=11
)

def style_function(feature):
    return {
        'opacity': 0.7,
        'weight': 1,
        'fillOpacity':0,
    }

folium.GeoJson(
    seoul_sgg_geo_2,
    style_function=style_function,
).add_to(viz_map_1)

top = seoul_sgg_stat ['만명당_매장수'].quantile(0.9) # 상위 10%값을 얻기 위한 코드

for idx in seoul_sgg_stat.index:
    lat = seoul_sgg_stat.loc[idx, '위도']
    lng = seoul_sgg_stat.loc[idx, '경도']
    r = seoul_sgg_stat.loc[idx, '만명당_매장수']
    if r > top:
        fillColor = 'red'
    else:
        fillColor = 'green'
    
    folium.CircleMarker(
        location=[lat, lng], 
        color='#FFFF00',     
        fill_color=fillColor, 
        fill_opacity=0.7,
        weight=1.5,
        radius= r * 10
    ).add_to(viz_map_1)

viz_map_1

인구수대비 스타벅스의 수는 종로구 >> 중구 >> 강남구 이렇게 나타므로

주민등록인구와 스타벅스 매장수는 서로 비례하지 않은것으로 나타난다.

2.스타벅스 매장수와 종사자수 비교

가정 : 직장인이 많은 지역에 스타벅스 매장이 많이 입지해 있을것이다.

seoul_sgg_stat['종사자수_만명당_매장수'] = seoul_sgg_stat['스타벅스_매장수']/(seoul_sgg_stat['종사자수']/10000)
seoul_sgg_stat.head() 
시군구코드 시군구명 위도 경도 스타벅스_매장수 주민등록인구 종사자수 사업체수 만명당_매장수 종사자수_만명당_매장수
0 11320 도봉구 37.665861 127.031767 3 323752.0 72939.0 18628.0 0.092664 0.411303
1 11380 은평구 37.617612 126.922700 8 479607.0 93631.0 24681.0 0.166803 0.854418
2 11230 동대문구 37.583801 127.050700 9 352570.0 138400.0 31324.0 0.255268 0.650289
3 11590 동작구 37.496504 126.944307 11 398205.0 106159.0 19793.0 0.276240 1.036182
4 11545 금천구 37.460097 126.900155 11 244564.0 242686.0 33814.0 0.449780 0.453261
seoul_sgg_geo_1 = json.load(open(SGG_GEOJSON_FILE_PATH, encoding='utf-8'))

viz_map_1 = folium.Map(
    location=[37.573050, 126.979189],
    tiles='CartoDB dark_matter',
    zoom_start=11
)

folium.GeoJson(
    seoul_sgg_geo_1,
    style_function=style_function,
).add_to(viz_map_1)

top = seoul_sgg_stat['종사자수_만명당_매장수'].quantile(0.9) # 상위값 3개를 가져오기 위함
for idx in seoul_sgg_stat.index:
    name = seoul_sgg_stat.at[idx, '시군구명']
    lat = seoul_sgg_stat.loc[idx, '위도']
    lng = seoul_sgg_stat.loc[idx, '경도']
    r = seoul_sgg_stat.loc[idx, '종사자수_만명당_매장수']
    
    if r > top:
        fillColor = '#FF3300'
    else:
        fillColor = '#CCFF33'
    
    folium.CircleMarker(
        location=[lat, lng], 
        color='#FFFF00', 
        fill_color=fillColor, 
        fill_opacity=0.7,
        weight=1.5,
        radius= r * 10
    ).add_to(viz_map_1)

viz_map_1

서대문구 >> 용산구 >> 종로구 순으로 보였다.

seoul_sgg_stat_sort2 = seoul_sgg_stat.sort_values(['종사자수'],ascending=False)
seoul_sgg_stat_sort3 =seoul_sgg_stat.sort_values(['스타벅스_매장수'],ascending=False)
plt.figure(figsize=(22,10))

plt.subplot(211)
plt.bar(seoul_sgg_stat_sort2['시군구명'],seoul_sgg_stat_sort2['종사자수'],color='green')
plt.title('서울시 구별 종사자수 ', fontsize=20)
plt.ylabel('종사자수', fontsize=18)


plt.subplot(212)
plt.bar(seoul_sgg_stat_sort3['시군구명'],seoul_sgg_stat_sort3['스타벅스_매장수'],color='green')
plt.title('서울시 구별 스타벅스 매장수 ', fontsize=20)
plt.ylabel('스타벅스_매장수', fontsize=18)

plt.show()

종사자수와 스타벅스 매장수가 어느정도 비례관계를 보이므로 두번째 가설은 어느정도 타당한것으로 보인다.

보완해야할점

  • 관광객의 영향도 있을것이다.
  • fodium의 지도가 구명이 나오질 않았다.
profile
집에가고싶다

0개의 댓글