일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 스타터스부트캠프
- 유데미큐레이션
- 유데미부트캠프
- Leetcode
- 정렬
- 데이터프레임
- 넘파이
- DataFrame
- 데이터분석
- 브루트포스 알고리즘
- 데이터드리븐
- 태블로
- Til
- Tableau
- pandas
- 유데미코리아
- 백준
- 데이터시각화
- 판다스
- 코딩테스트
- 그리디 알고리즘
- ndarray
- 취업부트캠프
- matplotlb
- numpy
- 부트캠프후기
- 유데미
- python
- 파이썬
- 시각화
- Today
- Total
Diary, Data, IT
[미니프로젝트] 전국과 제주도 상권 정보 분석/데이터 시각화 본문
전국과 제주도 상권 정보 분석/시각화¶
from IPython.core.display import display, HTML
display(HTML("<style>.container {width:90% !important;}</style>"))
- 라이브러리 임포트
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams['font.family']='NanumGothic'
plt.rcParams['axes.unicode_minus']=False
import warnings
warnings.filterwarnings(action='ignore')
1. 데이터 수집¶
1.1 데이터프레임 생성¶
17개 파일의 데이터를 합쳐 하나의 데이터프레임으로 생성
column에 NaN값이나 여러 type의 데이터가 섞여 있으면 DtypeWarning 발생
dtype option으로 타입을 명시해주거나 low_memory = False로 지정해 주면 경고 메시지가 출력되지 않는다.
from glob import glob
data_list = [x for x in glob('data/*.csv') if '소상공인시장진흥공단' in x]
df = pd.DataFrame()
for data in data_list:
df1 = pd.read_csv(data, low_memory = False)
df = pd.concat([df, df1], axis = 0)
# 컬럼갯수 최대 지정
pd.options.display.max_columns=39
df.head()
상가업소번호 | 상호명 | 지점명 | 상권업종대분류코드 | 상권업종대분류명 | 상권업종중분류코드 | 상권업종중분류명 | 상권업종소분류코드 | 상권업종소분류명 | 표준산업분류코드 | 표준산업분류명 | 시도코드 | 시도명 | 시군구코드 | 시군구명 | 행정동코드 | 행정동명 | 법정동코드 | 법정동명 | 지번코드 | 대지구분코드 | 대지구분명 | 지번본번지 | 지번부번지 | 지번주소 | 도로명코드 | 도로명 | 건물본번지 | 건물부번지 | 건물관리번호 | 건물명 | 도로명주소 | 구우편번호 | 신우편번호 | 동정보 | 층정보 | 호정보 | 경도 | 위도 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 25033300 | 동그라미중고타이어 | NaN | D | 소매 | D23 | 자동차/자동차용품 | D23A04 | 타이어판매 | G45211 | 자동차 타이어 및 튜브 판매업 | 42 | 강원도 | 42150 | 강릉시 | 4215057100 | 포남1동 | 4.215011e+09 | 포남동 | 4215011100110960006 | 1 | 대지 | 1096 | 6.0 | 강원도 강릉시 포남동 1096-6 | 4.215032e+11 | 강원도 강릉시 가작로 | 270 | NaN | 4215011100110960006010791 | NaN | 강원도 강릉시 가작로 270 | 210110.0 | 25488.0 | 1 | NaN | NaN | 128.904472 | 37.770252 |
1 | 17174549 | 세인트존스호텔Ohcrab | NaN | O | 숙박 | O01 | 호텔/콘도 | O01A01 | 호텔/콘도 | NaN | NaN | 42 | 강원도 | 42150 | 강릉시 | 4215058000 | 초당동 | 4.215011e+09 | 강문동 | 4215011300100010001 | 1 | 대지 | 1 | 1.0 | 강원도 강릉시 강문동 1-1 | 4.215032e+11 | 강원도 강릉시 창해로 | 307 | NaN | 4215011300100010001017124 | 세인트존스호텔 | 강원도 강릉시 창해로 307 | 210120.0 | 25467.0 | NaN | NaN | NaN | 128.920908 | 37.791299 |
2 | 17174079 | 평창라마다호텔 | NaN | O | 숙박 | O01 | 호텔/콘도 | O01A01 | 호텔/콘도 | NaN | NaN | 42 | 강원도 | 42760 | 평창군 | 4276038000 | 대관령면 | 4.276038e+09 | 대관령면 | 4276038024102450066 | 1 | 대지 | 245 | 66.0 | 강원도 평창군 대관령면 횡계리 245-66 | 4.276045e+11 | 강원도 평창군 대관령면 오목길 | 107 | NaN | 4276038024102450036000001 | NaN | 강원도 평창군 대관령면 오목길 107 | 232954.0 | 25342.0 | NaN | NaN | NaN | 128.717971 | 37.660051 |
3 | 17173904 | 호텔탑스텐스카이라운지 | NaN | O | 숙박 | O01 | 호텔/콘도 | O01A01 | 호텔/콘도 | NaN | NaN | 42 | 강원도 | 42150 | 강릉시 | 4215035000 | 옥계면 | 4.215035e+09 | 옥계면 | 4215035029100920001 | 1 | 대지 | 92 | 1.0 | 강원도 강릉시 옥계면 금진리 92-1 | 4.215032e+11 | 강원도 강릉시 옥계면 헌화로 | 455 | 34.0 | 4215035029100920001000002 | NaN | 강원도 강릉시 옥계면 헌화로 455-34 | 210831.0 | 25633.0 | NaN | NaN | NaN | 129.052902 | 37.654680 |
4 | 17175299 | 족발야시장 | NaN | Q | 음식 | Q01 | 한식 | Q01A08 | 족발/보쌈전문 | I56111 | 한식 음식점업 | 42 | 강원도 | 42150 | 강릉시 | 4215055000 | 교1동 | 4.215011e+09 | 교동 | 4215011000118650014 | 1 | 대지 | 1865 | 14.0 | 강원도 강릉시 교동 1865-14 | 4.215045e+11 | 강원도 강릉시 율곡초교길 | 41 | NaN | 4215011000118650014003453 | NaN | 강원도 강릉시 율곡초교길 41 | 210924.0 | 25513.0 | NaN | NaN | NaN | 128.878636 | 37.765339 |
2. 데이터 확인 및 전처리¶
2.1 데이터프레임 정보¶
df.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 2245938 entries, 0 to 86652 Data columns (total 39 columns): # Column Dtype --- ------ ----- 0 상가업소번호 int64 1 상호명 object 2 지점명 object 3 상권업종대분류코드 object 4 상권업종대분류명 object 5 상권업종중분류코드 object 6 상권업종중분류명 object 7 상권업종소분류코드 object 8 상권업종소분류명 object 9 표준산업분류코드 object 10 표준산업분류명 object 11 시도코드 int64 12 시도명 object 13 시군구코드 int64 14 시군구명 object 15 행정동코드 int64 16 행정동명 object 17 법정동코드 float64 18 법정동명 object 19 지번코드 int64 20 대지구분코드 int64 21 대지구분명 object 22 지번본번지 int64 23 지번부번지 float64 24 지번주소 object 25 도로명코드 float64 26 도로명 object 27 건물본번지 int64 28 건물부번지 float64 29 건물관리번호 object 30 건물명 object 31 도로명주소 object 32 구우편번호 float64 33 신우편번호 float64 34 동정보 object 35 층정보 object 36 호정보 object 37 경도 float64 38 위도 float64 dtypes: float64(8), int64(8), object(23) memory usage: 685.4+ MB
서브셋 만들기¶
# 컬럼명 가져오기
df.columns
Index(['상가업소번호', '상호명', '지점명', '상권업종대분류코드', '상권업종대분류명', '상권업종중분류코드', '상권업종중분류명', '상권업종소분류코드', '상권업종소분류명', '표준산업분류코드', '표준산업분류명', '시도코드', '시도명', '시군구코드', '시군구명', '행정동코드', '행정동명', '법정동코드', '법정동명', '지번코드', '대지구분코드', '대지구분명', '지번본번지', '지번부번지', '지번주소', '도로명코드', '도로명', '건물본번지', '건물부번지', '건물관리번호', '건물명', '도로명주소', '구우편번호', '신우편번호', '동정보', '층정보', '호정보', '경도', '위도'], dtype='object')
필요한 컬럼만 추출하여 서브셋 만들기¶
- 서브셋을 만들 때는 copy()로 깊은복사하여 원본을 변경하지 않도록 함
df_store = df[['상호명', '상권업종대분류명', '상권업종중분류명', '상권업종소분류명', '시도명', '시군구명', '행정동명', '법정동명', '경도', '위도']].copy()
df_store.head()
상호명 | 상권업종대분류명 | 상권업종중분류명 | 상권업종소분류명 | 시도명 | 시군구명 | 행정동명 | 법정동명 | 경도 | 위도 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 동그라미중고타이어 | 소매 | 자동차/자동차용품 | 타이어판매 | 강원도 | 강릉시 | 포남1동 | 포남동 | 128.904472 | 37.770252 |
1 | 세인트존스호텔Ohcrab | 숙박 | 호텔/콘도 | 호텔/콘도 | 강원도 | 강릉시 | 초당동 | 강문동 | 128.920908 | 37.791299 |
2 | 평창라마다호텔 | 숙박 | 호텔/콘도 | 호텔/콘도 | 강원도 | 평창군 | 대관령면 | 대관령면 | 128.717971 | 37.660051 |
3 | 호텔탑스텐스카이라운지 | 숙박 | 호텔/콘도 | 호텔/콘도 | 강원도 | 강릉시 | 옥계면 | 옥계면 | 129.052902 | 37.654680 |
4 | 족발야시장 | 음식 | 한식 | 족발/보쌈전문 | 강원도 | 강릉시 | 교1동 | 교동 | 128.878636 | 37.765339 |
서브셋 데이터 확인¶
# 데이터 정보(메모리 용량)
df_store.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 2245938 entries, 0 to 86652 Data columns (total 10 columns): # Column Dtype --- ------ ----- 0 상호명 object 1 상권업종대분류명 object 2 상권업종중분류명 object 3 상권업종소분류명 object 4 시도명 object 5 시군구명 object 6 행정동명 object 7 법정동명 object 8 경도 float64 9 위도 float64 dtypes: float64(2), object(8) memory usage: 188.5+ MB
결측치분석/처리¶
df_store.isnull().sum()
상호명 2 상권업종대분류명 0 상권업종중분류명 0 상권업종소분류명 0 시도명 0 시군구명 0 행정동명 11839 법정동명 1453 경도 0 위도 0 dtype: int64
#상호명이 결측치인 자료들만 제거
df_store.dropna(subset = '상호명', inplace = True)
2.2 상권업종분류¶
df_store['상권업종대분류명'].unique()
array(['소매', '숙박', '음식', '학문/교육', '생활서비스', '부동산', '관광/여가/오락', '스포츠'], dtype=object)
df_store['상권업종중분류명'].unique()
array(['자동차/자동차용품', '호텔/콘도', '한식', '가구소매', '학원기타', '유흥주점', '철물/난방/건설자재소매', '주유소/충전소', '가방/신발/액세서리', '가정/주방/인테리어', '커피점/카페', '캠프/별장/펜션', '음/식료품소매', '기타판매업', '화장품소매', '부동산중개', '선물/팬시/기념품', '개인/가정용품수리', '학원-음악미술무용', '민박/하숙', '의복의류', '요가/단전/마사지', '세탁/가사서비스', '주택수리', '분식', '인력/고용/용역알선', '사진/광학/정밀기기소매', '가전제품소매', '종합소매점', '사무/문구/컴퓨터', '이/미용/건강', '학원-어학', '일식/수산물', '무도/유흥/가무', '모텔/여관/여인숙', '제과제빵떡케익', '자동차/이륜차', '광고/인쇄', '취미/오락관련소매', '학원-보습교습입시', '대중목욕탕/휴게', '패스트푸드', '실내운동시설', '놀이/여가/취미', '건강/미용식품', '닭/오리요리', '학원-창업취업취미', '시계/귀금속소매', '중식', '운동/경기용품소매', '페인트/유리제품소매', '대행업', '실외운동시설', '중고품소매/교환', '의약/의료품소매', '유아용품', '학원-예능취미체육', '유아교육', '학문교육기타', '별식/퓨전요리', '책/서적/도서', '기타서비스업', 'PC/오락/당구/볼링등', '분양', '애견/애완/동물', '양식', '장례/묘지', '물품기기대여', '기타음식업', '사진', '도서관/독서실', '행사/이벤트', '부페', '운송/배달/택배', '개인서비스', '학원-자격/국가고시', '예식/의례/관혼상제', '음식배달서비스', '경마/경륜/성인오락', '스포츠/운동', '종교용품판매', '운영관리시설', '학원-컴퓨터', '예술품/골동품/수석/분재', '평가/개발/관리', '연극/영화/극장', '법무세무회계', '유스호스텔', '부동산관련서비스'], dtype=object)
df_store['상권업종중분류명'].nunique()
89
df_store['상권업종소분류명'].nunique()
716
상권업종분류표¶
df_store_class = df_store[['상권업종대분류명', '상권업종중분류명', '상권업종소분류명']].drop_duplicates(keep = 'first').sort_values(['상권업종대분류명','상권업종중분류명','상권업종소분류명'])
# 상권업종 분류표 모두보기(최대 행 수 지정)
pd.options.display.max_rows = 20
df_store_class
상권업종대분류명 | 상권업종중분류명 | 상권업종소분류명 | |
---|---|---|---|
8094 | 관광/여가/오락 | PC/오락/당구/볼링등 | 기원 |
2885 | 관광/여가/오락 | PC/오락/당구/볼링등 | 당구장 |
4683 | 관광/여가/오락 | PC/오락/당구/볼링등 | 볼링장 |
44597 | 관광/여가/오락 | PC/오락/당구/볼링등 | 비디오감상실 |
53746 | 관광/여가/오락 | PC/오락/당구/볼링등 | 오락용사격장 |
... | ... | ... | ... |
35146 | 학문/교육 | 학원기타 | 학원-모델 |
101249 | 학문/교육 | 학원기타 | 학원-실내운전 |
11474 | 학문/교육 | 학원기타 | 학원-심리변론 |
56976 | 학문/교육 | 학원기타 | 학원-역학 |
9856 | 학문/교육 | 학원기타 | 학원-침술 |
716 rows × 3 columns
3. 전국 상가 등록 현황¶
3.1 업종 대분류별 상가 갯수¶
df_store_class1 = df_store['상권업종대분류명'].value_counts()
df_store_class1
음식 791783 소매 727769 생활서비스 377242 학문/교육 157123 부동산 80471 관광/여가/오락 47527 숙박 38841 스포츠 25180 Name: 상권업종대분류명, dtype: int64
# 막대그래프
plt.rcParams['figure.figsize'] = (12, 5)
fig, ax = plt.subplots(1,2, facecolor = 'snow')
ax[0].bar(df_store_class1.index, df_store_class1, color = 'orange')
ax[0].grid(axis = 'y', ls = ':')
ax[0].set_xticklabels(df_store_class1.index, rotation = 45)
# 파이그래프
ax[1].pie(df_store_class1, labels = df_store_class1.index, autopct = '%.1f%%', pctdistance = 0.7,
wedgeprops = {'width': 0.7})
plt.suptitle('전국 업종별 상가 등록 현황', size = 20)
plt.tight_layout()
plt.show()
음식, 소매업이 가장 많으며 숙박, 관광, 스포츠 상가가 적은 편으로 나타났다.
음식/소매업은 전체의 67.7%로 거의 70%에 육박할 정도로 대부분을 차지하고 있었다.
전체적으로 생활과 밀접한 관련이 있고, 거주민들이 필수적으로 이용하는 업종이 많이 존재하는 것을 확인했다.
3.2 시도별 상가 갯수¶
df_store_sido = df_store['시도명'].value_counts()
df_store_sido
경기도 516790 서울특별시 325879 경상남도 158901 부산광역시 140028 경상북도 135299 충청남도 115651 전라남도 109831 인천광역시 107679 전라북도 106471 강원도 105273 대구광역시 96784 충청북도 86653 대전광역시 69583 광주광역시 65786 제주특별자치도 47851 울산광역시 45504 세종특별자치시 11973 Name: 시도명, dtype: int64
# 막대그래프
plt.figure(facecolor = 'snow')
plt.subplot(121)
plt.bar(df_store_sido.index, df_store_sido, color = 'orange')
plt.xticks(rotation = 45)
plt.grid(axis = 'y', ls = ':')
# 파이그래프
plt.subplot(122)
plt.pie(df_store_sido, labels = df_store_sido.index, autopct = '%.1f%%', pctdistance = 0.7,
wedgeprops = {'width': 0.7})
plt.suptitle('전국 시도별 상가 등록 현황', size = 20)
plt.tight_layout()
plt.show()
경기도에 가장 많이 존재했으며, 비교적 최근에 생긴 도시인 세종에 가장 적은 수의 상가가 있었다.
상가 수와 거주민 수에 관계가 있는지 살펴보고자 인구 밀도 데이터를 추가적으로 불러와서 살펴보았다.
인구 밀도와 시도별 상가 등록 현황 비교¶
df_people = pd.read_csv('data/202110_202110_주민등록인구및세대현황_월간.csv', encoding = 'cp949')
df_people = df_people[['행정구역','2021년10월_총인구수']]
df_people.columns = ['행정구역', '총인구수']
df_people['총인구수'] = df_people['총인구수'].str.replace(',', '').astype('int64')
df_people_sido = df_people[df_people['행정구역'].str.contains('00000000')].copy()
df_people_sido['행정구역'] = df_people_sido['행정구역'].str.split(' ').str[0]
df_people_sido.sort_values('총인구수', ascending = False, inplace = True)
df_people_sido
행정구역 | 총인구수 | |
---|---|---|
1273 | 경기도 | 13549577 |
0 | 서울특별시 | 9532428 |
452 | 부산광역시 | 3356311 |
3469 | 경상남도 | 3318161 |
826 | 인천광역시 | 2945009 |
3100 | 경상북도 | 2627925 |
674 | 대구광역시 | 2390721 |
2265 | 충청남도 | 2118977 |
2754 | 전라남도 | 1834653 |
2492 | 전라북도 | 1789770 |
2095 | 충청북도 | 1596948 |
1882 | 강원도 | 1537717 |
1102 | 대전광역시 | 1454228 |
999 | 광주광역시 | 1442454 |
1187 | 울산광역시 | 1122566 |
3806 | 제주특별자치도 | 676569 |
1249 | 세종특별자치시 | 368276 |
fig, ax1 = plt.subplots()
ax1.bar(df_people_sido['행정구역'], df_people_sido['총인구수'], width = -0.4, align = 'edge', color = 'skyblue', label = '시도별 총 인구수')
plt.legend()
ax1.set_xticklabels(df_people_sido['행정구역'], rotation = 45)
ax2 = ax1.twinx()
ax2.bar(df_store_sido.index, df_store_sido, width = 0.4, align = 'edge', color = 'pink', label = '시도별 상가수')
plt.legend(loc = (0.85, 0.85))
ax1.set_xlabel('시도')
ax1.set_ylabel('총 인구수')
ax2.set_ylabel('총 상가수')
plt.title('시도별 총 인구와 상가 수 현황', size = 15)
plt.grid(axis = 'y', ls = ':')
plt.show()
시도별 총 인구 수와 상가 수를 비교했을 때, 지역별 분포가 거의 유사한 형태를 띄고있기 때문에 둘은 밀접하게 관련이 있다는 사실을 알 수 있었다.
3.3 시도별 업종대분류별 상가 현황¶
df_store_pivot = df_store.pivot_table(index = '시도명', columns = '상권업종대분류명', values = '경도', aggfunc = 'count')
plt.figure(figsize = (15, 5))
sns.heatmap(df_store_pivot, annot = True, fmt = 'd')
plt.show()
전체 업종 등록 현황에서 대부분을 차지하는 것으로 나타났던 음식/소매업이 모든 지역에서 뚜렷하게 많이 존재하는 것으로 나타났다.
지역별로 차이가 돋보이는 업종은 학문/교육
이 있었다. 서울과 경기도에서 교육 관련 상가가 지방에 비해 두드러지게 많이 존재함을 확인할 수 있다.
하지만, 전체적인 업종의 분포가 음식/소매업에 몰려있기 때문에 대부분의 값이 매우 작은 것으로 취급되어 히트맵을 통해서는 많은 정보를 얻기 어려웠다.
본 프로젝트는 대표적인 관광지로 잘 알려져있는 제주도와 전국의 상가를 비교하여, 제주도에서 관광과 관련된 업종들이 특히 도드라지고 있는지를 그래프를 통해 확인하고자 한다.
4. 제주도 상가 현황¶
df_store_jeju = df_store[df_store['시도명'] == '제주특별자치도'].copy()
4.1 제주도 업종별 상가 등록 현황¶
df_store_jeju_count = df_store_jeju['상권업종대분류명'].value_counts()
df_store_jeju_count
음식 20096 소매 13287 생활서비스 6182 숙박 3064 학문/교육 2782 부동산 1085 관광/여가/오락 849 스포츠 506 Name: 상권업종대분류명, dtype: int64
# 막대그래프
plt.rcParams['figure.figsize'] = (12, 5)
fig, ax = plt.subplots(1,2, facecolor = 'snow')
ax[0].bar(df_store_jeju_count.index, df_store_jeju_count, color = 'orange')
ax[0].grid(axis = 'y', ls = ':')
ax[0].set_xticklabels(df_store_jeju_count.index, rotation = 45)
# 파이그래프
ax[1].pie(df_store_jeju_count, labels = df_store_jeju_count.index, autopct = '%.1f%%', pctdistance = 0.7,
wedgeprops = {'width': 0.7})
plt.suptitle('제주도 업종별 상가 등록 현황', size = 20)
plt.tight_layout()
plt.show()
4.2 전국과 제주도 업종별 상가 등록 현황 비교¶
#업종별 비율을 담은 시리즈 생성
df_store_class1_per = df_store_class1/sum(df_store_class1)
df_store_jeju_per = df_store_jeju_count/sum(df_store_jeju_count)
plt.bar(df_store_class1_per.index, df_store_class1_per, width = -0.4, align = 'edge', color = 'lightgreen', label = '전국')
plt.bar(df_store_jeju_per.index, df_store_jeju_per, width = 0.4, align = 'edge', color = 'orange', label = '제주도')
plt.title('전국과 제주도 업종별 상가 현황')
plt.ylabel('업종별 상가 비율')
plt.legend()
plt.show()
전국의 업종별 분포 현황과 제주도의 업종별 분포 현황을 비교했을 때, 제주도는 음식
과 숙박
업종의 상가가 특히 많이 존재한다는 사실을 알 수 있으며, 해당 업종들은 관광과 직접적인 관련이 있다고 할 수 있다.
하지만 관광/여가/오락
업종은 전체 지역과 큰 차이를 보이지 않았는데, 그 이유는 본 데이터에서 관광 업종은 주점, 당구장 등 일상생활과 밀접한 오락시설이 많고 제주도의 관광지 정보를 담고있지는 않기때문에 전국과 큰 차이가 없는 것으로 추측했다.
4.3 제주도 업종별 위치 지도 그리기¶
관광객이 주로 방문하는 카테고리인 음식과 숙박업소가 어디에 많이 위치하는지 그래프(지도)를 통해 확인한다.
제주도 지역 분류는 관광지가 많이 위치하는 구역들, 통상적으로 제주도를 분류하는 기준을 이용했다.
df_store_jeju['법정동명'].unique()
array(['서귀동', '대정읍', '한림읍', '노형동', '용담일동', '건입동', '화북일동', '애월읍', '조천읍', '이도이동', '삼도일동', '동홍동', '도두일동', '한경면', '서홍동', '성산읍', '남원읍', '용담이동', '연동', '구좌읍', '일도이동', '우도면', '강정동', '화북이동', '이도일동', '중문동', '월평동', '도남동', '안덕면', '삼도이동', '서호동', '아라이동', '대포동', '표선면', '아라일동', '외도일동', '일도일동', '용담삼동', '신효동', '이호일동', '영평동', '상예동', '하효동', '색달동', '호근동', '상효동', '삼양이동', '하예동', '오라이동', '삼양일동', '토평동', '오등동', '법환동', '오라일동', '해안동', '추자면', '도련일동', '오라삼동', '보목동', '회천동', '봉개동', '회수동', '하원동', '내도동', '도순동', '외도이동', '도두이동', '도련이동', '용강동', '이호이동', '도평동', '삼양삼동', '영남동'], dtype=object)
df_store_jeju['행정동명'].unique()
array(['중앙동', '천지동', '대정읍', '한림읍', '노형동', '용담1동', '건입동', '화북동', '애월읍', '조천읍', '이도2동', '삼도1동', '동홍동', '도두동', '한경면', '서홍동', '성산읍', '남원읍', '용담2동', '연동', '구좌읍', '일도2동', '우도면', '대천동', '이도1동', '중문동', '아라동', '안덕면', '삼도2동', '정방동', '대륜동', '표선면', '외도동', '일도1동', '효돈동', '이호동', '예래동', '영천동', '삼양동', '오라동', '송산동', '추자면', '봉개동'], dtype=object)
df_store_jeju.head()
상호명 | 상권업종대분류명 | 상권업종중분류명 | 상권업종소분류명 | 시도명 | 시군구명 | 행정동명 | 법정동명 | 경도 | 위도 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 동경부동산 | 부동산 | 부동산중개 | 부동산중개 | 제주특별자치도 | 서귀포시 | 중앙동 | 서귀동 | 126.561556 | 33.250877 |
1 | 에프케이알레그리아호텔제주 | 숙박 | 호텔/콘도 | 호텔/콘도 | 제주특별자치도 | 서귀포시 | 천지동 | 서귀동 | 126.559015 | 33.248179 |
2 | 정아기획인쇄사 | 생활서비스 | 광고/인쇄 | 인쇄종합 | 제주특별자치도 | 서귀포시 | 천지동 | 서귀동 | 126.559047 | 33.250127 |
3 | 해녀촌식당 | 음식 | 한식 | 한식/백반/한정식 | 제주특별자치도 | 서귀포시 | 대정읍 | 대정읍 | 126.274126 | 33.166521 |
4 | 아빠가닭튀기는집 | 음식 | 유흥주점 | 호프/맥주 | 제주특별자치도 | 제주시 | 한림읍 | 한림읍 | 126.264860 | 33.412363 |
jeju_gu = ['조천읍', '구좌읍', '성산읍', '표선면', '남원읍', '안덕면', '대정읍', '한경면', '한림읍', '애월읍', '색달동', '대포동']
def jeju_map(x):
if ((x['법정동명'] in ['중문동', '색달동', '대포동']) | (x['행정동명'] == '중문동')):
return '중문'
elif x['행정동명'] in jeju_gu:
return x['행정동명']
else:
return x['시군구명']
df_store_jeju['새주소'] = df_store_jeju.apply(jeju_map, axis = 1)
df_store_jeju['새주소'].value_counts()
제주시 26416 서귀포시 6259 애월읍 2237 한림읍 1792 조천읍 1566 성산읍 1500 구좌읍 1438 대정읍 1392 중문 1227 표선면 1121 안덕면 1115 남원읍 1092 한경면 696 Name: 새주소, dtype: int64
#제주도 지역별 위치정보를 담은 데이터셋 생성
df_store_jeju_map = df_store_jeju.groupby('새주소')[['경도', '위도']].mean()
df_store_jeju_map
경도 | 위도 | |
---|---|---|
새주소 | ||
구좌읍 | 126.823403 | 33.526300 |
남원읍 | 126.697116 | 33.285706 |
대정읍 | 126.256454 | 33.232595 |
서귀포시 | 126.549272 | 33.252481 |
성산읍 | 126.906011 | 33.437766 |
안덕면 | 126.327702 | 33.263012 |
애월읍 | 126.374457 | 33.459246 |
제주시 | 126.518243 | 33.498782 |
조천읍 | 126.662153 | 33.518594 |
중문 | 126.425556 | 33.253128 |
표선면 | 126.815489 | 33.342962 |
한경면 | 126.207032 | 33.327662 |
한림읍 | 126.260886 | 33.405241 |
#제주도 음식 업종의 데이터만 추출
df_store_jeju_food = df_store_jeju[df_store_jeju['상권업종대분류명'] == '음식'].copy()
#이상치 제거
idx = df_store_jeju_food[df_store_jeju_food['경도'] > 128].index
df_store_jeju_food.drop(index = idx, inplace = True)
idx = df_store_jeju_food[df_store_jeju_food['위도'] > 33.7].index #추자도의 정보, 제외
df_store_jeju_food.drop(index = idx, inplace = True)
df_store_jeju_food.reset_index(drop = True, inplace = True)
sns.scatterplot(data = df_store_jeju_food, x = '경도', y = '위도', hue = '새주소', alpha = 0.5)
for gu in df_store_jeju_map.index:
plt.text(df_store_jeju_map.loc[gu][0], df_store_jeju_map.loc[gu][1], gu, ha = 'center', size = 12)
plt.title('제주도 식당 위치 지도', size = 20)
plt.legend(loc = (1.01, 0))
plt.show()
공항과 도심이 위치한 제주시와 양 옆인 조천읍, 애월읍에 식당이 많이 위치하고 있는 것을 알 수 있었다.
또한 제주시와 반대에 위치한 서귀포시에도 식당이 꽤 많이 존재함을 알 수 있다.
#제주도 숙박 업종의 데이터만 추출
df_store_jeju_hotel = df_store_jeju[df_store_jeju['상권업종대분류명'] == '숙박'].copy()
#이상치 제거
idx = df_store_jeju_hotel[df_store_jeju_hotel['경도'] > 128].index
df_store_jeju_hotel.drop(index = idx, inplace = True)
idx = df_store_jeju_hotel[df_store_jeju_hotel['위도'] > 33.7].index #추자도의 정보, 제외
df_store_jeju_hotel.drop(index = idx, inplace = True)
df_store_jeju_hotel.reset_index(drop = True, inplace = True)
sns.scatterplot(data = df_store_jeju_hotel, x = '경도', y = '위도', hue = '새주소', alpha = 0.5)
for gu in df_store_jeju_map.index:
plt.text(df_store_jeju_map.loc[gu][0], df_store_jeju_map.loc[gu][1], gu, ha = 'center', size = 12)
plt.title('제주도 숙박업소 위치 지도', size = 20)
plt.legend(loc = (1.01, 0))
plt.show()
숙박업소 또한 식당과 마찬가지로, 공항과 도심이 위치한 제주시와 양 옆인 조천읍, 애월읍에 숙박업소가 많이 위치하고 있는 것을 알 수 있었다.
특히 애월읍애 많은 숙박업소가 위치하는 것으로 보인다. 서귀포시와 성산읍에도 상당수 존재하는데, 성산읍은 관광지가 많은 곳이기도 하다.
4.4 제주도 구역별 업종 현황 비교¶
대략적으로 제주시, 애월읍, 조천읍, 서귀포시에 식당과 숙박업소가 많이 존재하는 것을 지도를 통해 알 수 있었지만,
구체적인 수치로도 나타내보고자 한다.
#업종별 수를 담은 데이터 생성
df_store_jeju_food_count = df_store_jeju_food['새주소'].value_counts().sort_values(ascending = False)
df_store_jeju_hotel_count = df_store_jeju_hotel['새주소'].value_counts().sort_values(ascending = False)
plt.subplot(121)
sns.barplot(x = df_store_jeju_food_count.index, y = df_store_jeju_food_count)
plt.xticks(rotation = 45)
plt.ylabel('상가 수')
plt.title('제주도 구역별 식당 수', size = 15)
plt.subplot(122)
sns.barplot(x = df_store_jeju_hotel_count.index, y = df_store_jeju_hotel_count)
plt.xticks(rotation = 45)
plt.ylabel('상가 수')
plt.title('제주도 구역별 숙박업소 수', size = 15)
# 전국과 제주도의 행정동별 숙박업소 평균 업종 수 표기
mean_total = df_store[df_store['상권업종대분류명'] == '숙박'].groupby('행정동명').count()['상호명'].mean()
mean_jeju = df_store[(df_store['상권업종대분류명'] == '숙박') & (df_store['시도명'] == '제주특별자치도')].groupby('행정동명').count()['상호명'].mean()
plt.axhline(mean_total)
plt.axhline(mean_jeju, color = 'red', ls = ':')
plt.show()
실제 수치로 살펴보니 식당, 숙박업소 모두 제주시에 가장 많이 위치해있다는 것을 확인
특히 식당의 경우 제주시와 다른 구역들의 차이가 매우 큰 것을 알 수 있다. 제주시는 관광객뿐만 아니라 도민들도 많이 거주하는 곳이기 때문으로 추측할 수 있다.
반면, 숙박업소는 관광객이 주로 이용하게 되는 업종이다. 이 경우에는 식당만큼 구역별 차이가 크게 벌어지지는 않는 것을 알 수 있다.
또한 빨간색 선으로 표기된 제주도의 전체 행정동별 숙소 수의 평균이 전국과 비교했을 때 확연하게 높은 것을 알 수 있었고, 제주도도 내부 지역보다 바다와 인접한 지역에 숙박업소의 수가 많으며 그래프에 나타난 행정동들이 제주도 내에서도 관광객 수가 많은 지역들임을 추측할 수 있다.
5. 결론¶
전국과 제주도의 업종별 상가 수를 비교한 결과 관광지인 제주도에는 생활과 직접적인 관련이 있는 업종들의 비율은 전국보다 약간 낮았고, 관광과 관련이 있는 음식과 숙박업소의 비율이 높은 것을 알 수 있었다.
제주도 내의 식당/숙박업의 분포를 비교했을 때, 도민도 많이 이용하는 식당의 경우에는 제주도의 번화가인 제주시에 많이 몰려있었지만, 도민들의 이용보다 관광객들의 이용이 많은 숙박업소의 경우에는 식당만큼 제주시에 많이 몰려있지는 않았고, 제주도 전역에 고루 존재하고 있었다.
제주도도 내부 지역보다 바다와 인접한 지역에 숙박업소의 수가 많아, 관광객들은 주로 제주도의 내부보다는, 바다를 따라 제주도 외곽지역을 순환하는 형태로 관광하고 있음을 추측할 수 있다.
'Project' 카테고리의 다른 글
[Tableau] Superstore Sales Tracking 프로젝트 (0) | 2023.07.10 |
---|---|
[Tableau] Airbnb 서비스 개선 프로젝트 (0) | 2023.07.06 |