folium을 이용한 서울시 스타벅스 이디야 입지 시각화

PNG

“왜 스타벅스 옆에는 항상 토종 커피 브랜드 ‘이디야’가 있을까?”와 같은 뉴스 기사를 보면 이디야는 스타벅스와 같이 장사가 잘 되는 점포 인근에 위치해 있다고 합니다. 실제로 Folium 라이브러리르 활용해 파이썬으로 스타벅스와 이디야 점포들의 위치를 서울시 지도 위에 시각화하여 직관적으로 확인해보도록 하겠습니다.

더 많은 파이썬 라이브러리 관련 정보

folium 설치

터미널을 실행하여 다음 명령어를 통해 folium을 설치합니다.

> pip install folium

라이브러리 임포트하기

아래와 같이 기본적인 파이썬 라이브러리들을 임포트합니다.

import folium
import json
import glob
import os
import pandas as pd
import numpy as np

스타벅스 및 이디야 데이터 가져오기

지도 상에 스타벅스, 이디야 점포들을 시각화하기 위해서는 각각의 점포들의 위치 정보를 알아야 합니다. 소상공인시장진흥공단에서 제공하는 상권정보 데이터에는 스타벅스, 이디야 뿐 아니라 전국의 다양한 업종의 상가업소 정보가 담겨있습니다. 이 데이터는 현재 공공데이터포털에서 다운로드 받을 수 있습니다. Open API로 데이터를 불러오는 방법도 있지만 이번 포스팅에서는 CSV 파일을 직접 다운로드 받아 시각화하도록 하겠습니다.

공공데이터포털 - 상가(상권)정보에 접속합니다. 19년 10월 현재 기준 가장 최근 데이터인소상공인시장진흥공단_상가업소정보_201906.zip을 다운로드합니다.

PNG

다운로드 받은 zip 파일을 파이썬 분석 환경 내 Data/ 폴더에 다음과 같이 풀어줍니다.
(Data 폴더 내에 CSV 파일들이 위치하도록 합니다.)

PNG

데이터 불러오기

다운로드 받은 CSV 파일을 불러오겠습니다. 4개 파일을 불러와 하나의 데이터프레임인 df로 할당합니다.

path = 'Data/'
allFiles = glob.glob(os.path.join(path+"*.csv"))

df = pd.DataFrame()
for file in allFiles:

    print(file)

    temp = pd.read_csv(file, engine='python', encoding='utf-8')
    df = pd.concat([df, temp])
Data\소상공인시장진흥공단_상가업소정보_201906_01.csv
Data\소상공인시장진흥공단_상가업소정보_201906_02.csv
Data\소상공인시장진흥공단_상가업소정보_201906_03.csv
Data\소상공인시장진흥공단_상가업소정보_201906_04.csv

데이터 컬럼 확인하기

print('컬럼 항목 수 :', len(df.columns))
list(df.columns)
컬럼 항목 수 : 39





['상가업소번호',
 '상호명',
 '지점명',
 '상권업종대분류코드',
 '상권업종대분류명',
 '상권업종중분류코드',
 '상권업종중분류명',
 '상권업종소분류코드',
 '상권업종소분류명',
 '표준산업분류코드',
 '표준산업분류명',
 '시도코드',
 '시도명',
 '시군구코드',
 '시군구명',
 '행정동코드',
 '행정동명',
 '법정동코드',
 '법정동명',
 '지번코드',
 '대지구분코드',
 '대지구분명',
 '지번본번지',
 '지번부번지',
 '지번주소',
 '도로명코드',
 '도로명',
 '건물본번지',
 '건물부번지',
 '건물관리번호',
 '건물명',
 '도로명주소',
 '구우편번호',
 '신우편번호',
 '동정보',
 '층정보',
 '호정보',
 '경도',
 '위도']

상권업종 간단하게 확인하기

print('='*70)
print('상권업종대분류명', set(df['상권업종대분류명']))
print('='*70)
print('상권업종중분류명', set(df['상권업종중분류명']))
print('='*70)
======================================================================
상권업종대분류명 {'음식', '생활서비스', '의료', '관광/여가/오락', '소매', '부동산', '숙박', '스포츠', '학문/교육'}
======================================================================
상권업종중분류명 {'가전제품소매', '경마/경륜/성인오락', '학원-음악미술무용', '철물/난방/건설자재소매', '사진', '유아용품', '애견/애완/동물', '패스트푸드', '학원-컴퓨터', '건강/미용식품', '유흥주점', '운동/경기용품소매', '일식/수산물', '양식', '종교용품판매', '학원-보습교습입시', '부동산중개', 'PC/오락/당구/볼링등', '세탁/가사서비스', '의료관련서비스업', '유아교육', '음식배달서비스', '놀이/여가/취미', '닭/오리요리', '유사의료업', '학원기타', '운영관리시설', '취미/오락관련소매', '사무/문구/컴퓨터', '약국/한약방', '대행업', '분양', '가정/주방/인테리어', '운송/배달/택배', '중고품소매/교환', '기타판매업', '주유소/충전소', '주택수리', '물품기기대여', '시계/귀금속소매', '법무세무회계', '인력/고용/용역알선', '의복의류', '부동산관련서비스', '이/미용/건강', '장례/묘지', '예술품/골동품/수석/분재', '부페', '광고/인쇄', '캠프/별장/펜션', '예식/의례/관혼상제', '모텔/여관/여인숙', '가구소매', '평가/개발/관리', '자동차/자동차용품', '스포츠/운동', '학문교육기타', '호텔/콘도', '화장품소매', '가방/신발/액세서리', '요가/단전/마사지', '실내운동시설', '도서관/독서실', '실외운동시설', '기타음식업', '무도/유흥/가무', '한식', '학원-자격/국가고시', '제과제빵떡케익', '사진/광학/정밀기기소매', '자동차/이륜차', '기타서비스업', '분식', '학원-어학', '대중목욕탕/휴게', '음/식료품소매', '수의업', '행사/이벤트', '종합소매점', '의약/의료품소매', '민박/하숙', '책/서적/도서', '커피점/카페', '유스호스텔', '학원-예능취미체육', '개인/가정용품수리', '학원-창업취업취미', '페인트/유리제품소매', '연극/영화/극장', '개인서비스', '별식/퓨전요리', '중식', '병원', '선물/팬시/기념품'}
======================================================================

데이터프레임의 컬럼 항목은 총 39개나 됩니다.
그러나 여기서 관심있는 부분은 스타벅스, 이디야와 같은 커피전문점의 위치정보입니다.
따라서 불필요한 컬럼은 제외하고, 관심있는 컬럼만 따로 떼어 dataset을 새로 만들겠습니다.

관련 정보만 추출

dataset = df[['상호명','지점명',
              '상권업종대분류명', '상권업종중분류명',
              '시도명', '시군구명', '행정동명',
              '위도', '경도']]

dataset.head()
상호명 지점명 상권업종대분류명 상권업종중분류명 시도명 시군구명 행정동명 위도 경도
0 커피빈코리아선릉로93길점 코리아선릉로93길점 음식 커피점/카페 서울특별시 강남구 역삼1동 37.505675 127.047883
1 프로포즈 NaN 음식 유흥주점 서울특별시 금천구 독산3동 37.471711 126.899220
2 싱싱커피&토스트 NaN 음식 패스트푸드 부산광역시 사상구 괘법동 35.159774 128.980455
3 와라와라호프 NaN 음식 유흥주점 서울특별시 강남구 대치1동 37.493922 127.061026
4 가락사우나내스낵 NaN 생활서비스 대중목욕탕/휴게 서울특별시 송파구 석촌동 37.500249 127.104071

커피 전문점 데이터 추출

여러 상권업소 중 서울시 내 커피 전문점 업소만 추출해 df_coffee를 정의합니다.
즉, 시도명서울특별시이면서, 상권업종중분류명커피점/카페인 경우를 뜻합니다.

df_coffee = dataset[(dataset['상권업종중분류명']=='커피점/카페')&(dataset['시도명']=='서울특별시')]
df_coffee.index = range(len(df_coffee))
print('서울시 내 커피 전문점 점포 수 :', len(df_coffee))
df_coffee.head()
서울시 내 커피 전문점 점포 수 : 18651
상호명 지점명 상권업종대분류명 상권업종중분류명 시도명 시군구명 행정동명 위도 경도
0 커피빈코리아선릉로93길점 코리아선릉로93길점 음식 커피점/카페 서울특별시 강남구 역삼1동 37.505675 127.047883
1 스완카페트 NaN 음식 커피점/카페 서울특별시 영등포구 대림3동 37.503693 126.897710
2 왕실 NaN 음식 커피점/카페 서울특별시 중구 명동 37.562274 126.982419
3 커피빈 코리아교대점 음식 커피점/카페 서울특별시 서초구 서초1동 37.492388 127.014217
4 고려대학교교육관쎄리오점 NaN 음식 커피점/카페 서울특별시 성북구 안암동 37.588485 127.031702

스타벅스 데이터 추출

먼저 서울시 내 커피 전문점 18,651개 업소 중 스타벅스 점포에 대한 데이터프레임을 만들어보겠습니다.

df_seoul_starbucks = df_coffee[df_coffee['상호명'].str.contains('스타벅스')]
df_seoul_starbucks.index = range(len(df_seoul_starbucks))
print('서울시 내 스타벅스 점포 수 :', len(df_seoul_starbucks))
df_seoul_starbucks.head()
서울시 내 스타벅스 점포 수 : 499
상호명 지점명 상권업종대분류명 상권업종중분류명 시도명 시군구명 행정동명 위도 경도
0 스타벅스 이태원점 음식 커피점/카페 서울특별시 용산구 이태원1동 37.534303 126.994781
1 스타벅스종로3가점 종로3가점 음식 커피점/카페 서울특별시 종로구 종로1.2.3.4가동 37.570585 126.990207
2 스타벅스 신사2점 음식 커피점/카페 서울특별시 서초구 잠원동 37.513663 127.019763
3 스타벅스커피여의도IFC1F NaN 음식 커피점/카페 서울특별시 영등포구 여의동 37.525172 126.924863
4 스타벅스 삼성역점 음식 커피점/카페 서울특별시 강남구 삼성1동 37.510038 127.063878

이디야 데이터 추출

이번엔 서울시 내 커피 전문점 18,651개 업소 중 이디야 점포에 대한 데이터프레임을 만들어보겠습니다.

df_seoul_ediya = df_coffee[df_coffee['상호명'].str.contains('이디야')]
df_seoul_ediya.index = range(len(df_seoul_ediya))
print('서울시 내 이디야 점포 수 :', len(df_seoul_ediya))
df_seoul_ediya.head()
서울시 내 이디야 점포 수 : 489
상호명 지점명 상권업종대분류명 상권업종중분류명 시도명 시군구명 행정동명 위도 경도
0 이디야커피 신길역점 음식 커피점/카페 서울특별시 영등포구 신길1동 37.515118 126.918062
1 이디야커피 이마트구로점 음식 커피점/카페 서울특별시 구로구 구로3동 37.484385 126.897870
2 이디야커피 중계롯데우성점 음식 커피점/카페 서울특별시 노원구 중계1동 37.646364 127.072754
3 이디야커피 금호역점 음식 커피점/카페 서울특별시 성동구 금호2.3가동 37.548427 127.017791
4 이디야커피 NaN 음식 커피점/카페 서울특별시 강남구 대치2동 37.508585 127.064790

서울시 구 별 스타벅스 수

서울시 구 별 스타벅스 점포의 수를 구해보겠습니다.

starbucks_gu = df_seoul_starbucks.groupby('시군구명')['상호명'].count().to_frame().sort_values(by='상호명', ascending=False)
starbucks_gu = starbucks_gu.reset_index()
starbucks_gu = starbucks_gu.set_index('시군구명')
starbucks_gu
상호명
시군구명
강남구 84
중구 55
서초구 47
종로구 33
영등포구 30
마포구 30
송파구 28
용산구 20
서대문구 19
강서구 17
광진구 14
강동구 13
금천구 13
성북구 13
구로구 11
은평구 10
양천구 10
노원구 9
관악구 9
동대문구 8
동작구 8
성동구 6
중랑구 6
강북구 5
도봉구 1

서울시 구 별 이디야 수

서울시 구 별 이디야 점포의 수를 구해보겠습니다.

ediya_gu = df_seoul_ediya.groupby('시군구명')['상호명'].count().to_frame().sort_values(by='상호명', ascending=False)
ediya_gu = ediya_gu.reset_index()
ediya_gu = ediya_gu.set_index('시군구명')
ediya_gu
상호명
시군구명
강남구 42
강서구 39
노원구 33
영등포구 27
송파구 27
중구 24
관악구 23
성북구 22
은평구 21
마포구 21
구로구 20
동대문구 19
서초구 17
성동구 17
양천구 17
광진구 16
종로구 16
서대문구 13
강동구 12
동작구 11
금천구 11
용산구 11
강북구 11
중랑구 11
도봉구 8

서울특별시 폴리곤 JSON 파일 불러오기

folium을 통해 서울시 지도 위에 점포들을 시각화하기 위해서는 지리 정보를 담고 있는 폴리곤 json 파일이 필요합니다.
PinkWink(github)에 접속 후 02.%20skorea_municipalities_geo_simple.jsonData/ 폴더에 다운로드하여 불러옵니다.

간편 다운로드 방법

skorea_municipalities_geo_simple.json 링크를 우클릭하여 다른 이름으로 링크 저장 합니다.
(출처:PinkWink(github))

geo_path = 'Data/02. skorea_municipalities_geo_simple.json'
geo_str = json.load(open(geo_path, encoding='utf-8'))

서울시 구 별 스타벅스 분포도 시각화

# 위치 파라미터 설정
loc = [37.5502, 126.982] # 위도(N), 경도(E)
data_size = len(df_seoul_starbucks)

# 지도 정의
map_starbucks = folium.Map(location=loc, zoom_start=12)
map_starbucks.choropleth(geo_data=geo_str,
              data = starbucks_gu['상호명'],
              columns=[starbucks_gu.index, starbucks_gu['상호명']],
              fill_color='PuRd',
              key_on='feature.id')


# 포인트 마커 추가

for i in range(data_size):

    folium.Marker(list(df_seoul_starbucks.iloc[i][['위도', '경도']]),
                 popup=df_seoul_starbucks.iloc[i][['지점명']],
                 icon=folium.Icon(color='green')).add_to(map_starbucks)

map_starbucks

서울시 구 별 이디야 분포도 시각화

# 위치 파라미터 설정
loc = [37.5502, 126.982] # 위도(N), 경도(E)
data2_size = len(df_seoul_ediya)

# 지도 정의
map_ediya = folium.Map(location=loc, zoom_start=12)
map_ediya.choropleth(geo_data=geo_str,
              data = ediya_gu['상호명'],
              columns=[ediya_gu.index, ediya_gu['상호명']],
              fill_color='PuRd',
              key_on='feature.id')


# 포인트 마커 추가

for i in range(data2_size):

    folium.Marker(list(df_seoul_ediya.iloc[i][['위도', '경도']]),
                 popup=df_seoul_ediya.iloc[i][['지점명']],
                 icon=folium.Icon(color='blue')).add_to(map_ediya)

map_ediya

서울시 스타벅스 및 이디야 입지 시각화

# 위치 파라미터 설정
loc = [37.5502, 126.982] # 위도(N), 경도(E)

data_size = len(df_seoul_starbucks)
data2_size = len(df_seoul_ediya)

# 지도 정의
map = folium.Map(location=loc,
                 tiles = 'Stamen Toner',
                 zoom_start=11)

# 포인트 마커 추가

for i in range(data_size):

    folium.Marker(list(df_seoul_starbucks.iloc[i][['위도', '경도']]),
                 popup=df_seoul_starbucks.iloc[i][['지점명']],
                 icon=folium.Icon(color='green')).add_to(map)


for i in range(data2_size):

    folium.Marker(list(df_seoul_ediya.iloc[i][['위도', '경도']]),
                 popup=df_seoul_ediya.iloc[i][['지점명']],
                 icon=folium.Icon(color='blue')).add_to(map)


map

점포 별 반경 100m 서클 시각화

# 위치 파라미터 설정

# 강남역 좌표
loc = [37.497895, 127.027565] # 위도(N), 경도(E)

data_size = len(df_seoul_starbucks)
data2_size = len(df_seoul_ediya)

# 지도 정의
map = folium.Map(location=loc,
                 tiles = 'Stamen Toner', # 'OpenStreetMap'
                 zoom_start=14)

# 포인트 서클 추가

for i in range(data_size):

    folium.Circle(list(df_seoul_starbucks.iloc[i][['위도', '경도']]),
                  radius = 100,
                  popup = df_seoul_starbucks.iloc[i]['지점명'],
                  color = '#2c9147',fill_color = '#2c9147').add_to(map)

for i in range(data2_size):

    folium.Circle(list(df_seoul_ediya.iloc[i][['위도', '경도']]),
                  radius = 100,
                  popup = df_seoul_ediya.iloc[i]['지점명'],
                  color = '#32408c',fill_color = '#32408c').add_to(map)

map

결론

점포 별 반경 100m 서클 시각화 결과는 강남역을 중심으로 확대한 지도를 보여주고 있습니다. 점포 마다 반경 100m 지역을 원으로 나타내고 있습니다. 반원을 점포의 직접적인 상권으로 가정하면, 초록색 원인 스타벅스와 파란색 원인 이디야 사이에 직접적인 상권이 겹치는 부분이 심심치 않게 보입니다. 또한, 두 브랜드 모두 특정 도로를 중심으로 분포하고 있는 모습을 확인할 수 있습니다. 시각화 결과만 놓고 보면 두 점포가 매우 가까이에 위치해 있는 것을 알 수 있습니다. 다만, 이는 두 브랜드를 비교한 결과이기때문에 스타벅스와 이디야만 근접해있다고 볼 수는 없다는 한계가 있습니다.

더 많은 파이썬 라이브러리 관련 정보

태그:

카테고리:

업데이트:

댓글남기기