[이전 글]
소상공인시장진흥공단 상가업소정보로 프랜차이즈 입점분석 (3)
구별 브랜드별 점포수
groupby와 pivot_table로 구별 스타벅스 이디야 매장 수 구하기
groupby로 구별 매장 수 구하기
df_cafe_vs = df_cafe.groupby(["시군구명", "브랜드명"])["상호명"].count()
df_cafe_vs.head()
# 인덱스 컬럼 만들기
df_cafe_vs = df_cafe_vs.reset_index()
df_cafe_vs.head()
# groupby '시군구명', '브랜드명' 으로 갯수 세기
df_cafe_vs.columns = ['구', '브랜드명', '매장수']
df_cafe_vs.head()
pivot_table로 구별 매장 수 구하기
pivot = pd.pivot_table(data=df_cafe,
index=["시군구명", "브랜드명"],
values="상호명", aggfunc="count")
pivot.head()
# 특정 구 데이터만 가져와서 보기
pivot.loc["강남구"]
막대그래프로 시각화하기
plt.figure(figsize=(15,4))
sns.barplot(data=df_cafe_vs, x="구", y="매장수", hue="브랜드명")
# barplot 정렬하기
plt.figure(figsize=(15, 4))
sns.barplot(data=df_cafe_vs.sort_values("매장수", ascending=False), x="구", y="매장수", hue="브랜드명")
group = df_cafe.groupby(["시군구명", "브랜드명"])["상호명"].count()
group.plot.bar(figsize=(15, 4))
group.unstack().plot.bar(figsize=(15, 4))
unstack? : 인덱스 값을 컬럼으로 올려주는 역할을 하는 함수, 인덱스 level별로 컬럼을 올려준다. level 설정을 하지 않으면 제일 높은 level의 인덱스부터 하나씩 올린다.
https://pandas.pydata.org/docs/user_guide/reshaping.html
https://seong6496.tistory.com/241
Folium으로 지도 활용하기
#지도의 중심 지정하기 위해 위도와 경도의 평균을 구해준다.
import folium
lat = df_cafe["위도"].mean()
long = df_cafe["경도"].mean()
lat, long
(37.5429213982126, 126.9887885123524)
스타벅스 이디야 카페 매장 전체 분포
m = folium.Map([lat, long], zoom_start=12, tiles="Stamen Toner")
for i in df_cafe.index:
sub_lat = df_cafe.loc[i, "위도"]
sub_long = df_cafe.loc[i, "경도"]
title = f"{df_cafe.loc[i, '상호명']} - {df_cafe.loc[i, '도로명주소']}"
color = "green"
if df_cafe.loc[i, "브랜드명"] == "이디야":
color = "blue"
folium.CircleMarker([sub_lat, sub_long],
radius=3,
color=color,
tooltip=title).add_to(m)
m
choropleth를 위한 GeoJSON 파일로드
- 구별로 매장 수를 표현하기 위해 GeoJSON 파일로드 : https://github.com/southkorea/seoul-maps
# 서울의 행정구역 경계를 GeoJSON으로 표현한 파일
# 이 파일을 불러와 구별 스타벅스와 이디야의 매장수를 표현한다.
geo_path = 'C:/Users/yobin/Downloads/seoul_municipalities_geo_simple.json'
import json
geo_json = json.load(open(geo_path, encoding="utf-8"))
스타벅스 매장 분포
df_star = df_cafe_vs[df_cafe_vs["브랜드명"] == "스타벅스"].copy()
df_star.head()
# geo_json 에서 구 이름 가져오기
geo_json["features"][0]['properties']['name']
'강동구'
# df_cafe_starbucks 로 스타벅스 매장 수 구하기
m = folium.Map([lat, long])
folium.Choropleth(
geo_data=geo_json,
name='choropleth',
data=df_star,
columns=['구', '매장수'],
key_on='feature.properties.name',
fill_color='YlGn',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='스타벅스 매장수'
).add_to(m)
m
이디야 매장 분포
df_ediya = df_cafe_vs[df_cafe_vs["브랜드명"] == "이디야"].copy()
df_ediya.head()
m = folium.Map([lat, long], titles='stamen toner')
folium.Choropleth(
geo_data=geo_json,
name='choropleth',
data=df_ediya,
columns=['구', '매장수'],
key_on='feature.properties.name',
fill_color='Blues',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='이디야 매장수'
).add_to(m)
for i in df_cafe.index:
sub_lat = df_cafe.loc[i, "위도"]
sub_long = df_cafe.loc[i, "경도"]
title = f"{df_cafe.loc[i, '상호명']} - {df_cafe.loc[i, '도로명주소']}"
color = "green"
if df_cafe.loc[i, "브랜드명"] == "이디야":
color = "blue"
folium.CircleMarker([sub_lat, sub_long],
radius=3,
color=color,
tooltip=title).add_to(m)
m
매장수 크기를 반영해 CircleMaker 만들기
# df_vs 변수에 구별 브랜드명을 pivot하여 스타벅스와 이디야 매장을 비교할 수 있는 형태로 만들어준다.
# ["스타벅스", "이디야"] 로 컬럼명을 변경해주고
# 스타벅스와 이디야의 매장을 비교한 값을 "매장수비교" 컬럼에 담아준다.
df_vs = df_cafe_vs.pivot(index="구", columns="브랜드명", values="매장수")
df_vs["매장수비교"] = df_vs["스타벅스"] - df_vs["이디야"] > 0
df_vs.head()
# 간단한 함수를 사용해서 스타벅스가 이디야보다 매장수가 많을 때 1을 출력하도록 한다.
df_vs["매장수비교"] = df_vs["매장수비교"].astype(float)
df_vs.head()
# 구를 컬럼명으로 사용하기 위해 reset_index 를 사용한다.
# 데이터 프레임을 df_vs 에 저장
df_vs = df_vs.reset_index()
df_vs.head()
choropleth로 매장수의 많고 적음에 따라 표현하기
# 스타벅스 매장 수 구하기
# CircleMarker의 radius 지정시 int 타입일 때 다음과 같은 타입오류가 나서 float type 으로 변경이 필요
m1 = folium.Map([lat, long], titles='stamen toner')
folium.Choropleth(
geo_data=geo_json,
name='choropleth',
data=df_vs,
columns=['구', '매장수비교'],
key_on='feature.properties.name',
fill_color='BuGn',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='매장수 비교'
).add_to(m1)
m1
df_gu_mean = df_cafe.pivot_table(index="시군구명", values=["경도", "위도"], aggfunc="mean")
df_gu_mean = df_gu_mean.reset_index()
df_gu_mean.head()
df_vs = df_vs.merge(df_gu_mean, how='inner', left_on="구", right_on="시군구명")
df_vs.head()
# 구별로 CircleMarker를 표현하기 위해서는 각 구의 위경도 값을 구해야 한다.
# 구별 위도와 경도를 가져와 평균 값을 구해서 사용
# 특정 구의 위경도의 평균을 구한다.
for i in df_vs.index:
sub_long = df_vs.loc[i, "경도"]
sub_lat = df_vs.loc[i, "위도"]
print(df_vs.loc[i, "구"], sub_lat, sub_long)
강남구 37.50574379723648 127.04612924851483
강동구 37.540316128928005 127.13541705768309
강북구 37.63114579912596 127.02289728220342
강서구 37.555966339807725 126.83788319929005
관악구 37.482054429288624 126.93521011850085
광진구 37.543769718110475 127.08329747837425
구로구 37.49406074774298 126.87745596750014
금천구 37.46928692765211 126.89219622133886
노원구 37.64239330513539 127.06717137772726
도봉구 37.66576544822702 127.04047354226729
동대문구 37.580700635471146 127.0549281321253
동작구 37.49570035386574 126.94890217041826
마포구 37.55548154197543 126.92300493503947
서대문구 37.566284229288875 126.93762476470604
서초구 37.493010911046724 127.01402160112261
성동구 37.55457943854072 127.03635911128876
성북구 37.59886024576221 127.02565170180027
송파구 37.5011799146096 127.1141353230951
양천구 37.52891847594385 126.86196683493063
영등포구 37.520781009585264 126.91390000535674
용산구 37.53468952777027 126.98251254628539
은평구 37.61406806596294 126.92041650466945
종로구 37.57615434804085 126.98723628325016
중구 37.56289726978086 126.986573350736
중랑구 37.596057768601725 127.08732220351888
신문기사와 유사하게 매장수에 따라 원의 크기를 다르게 그리기
cafes = ["스타벅스", "이디야"]
for cafe in cafes:
print(cafe)
스타벅스
이디야
df_vs.head(1)
np.sqrt(50)
7.0710678118654755
# 아래의 for문을 활용해서 스타벅스, 이디야로 매장수를 반영해 그린다.
# CircleMarker 의 radius 크기를 구해 원의 크기를 다르게 표현
# 또, 경도에 특정 숫자를 더해 두 개의 원이 겹치지 않게 그린다.
m = folium.Map([lat, long], zoom_start=11, tiles='stamen toner')
folium.Choropleth(
geo_data=geo_json,
name='choropleth',
data=df_vs,
columns=['구', '매장수비교'],
key_on='feature.properties.name',
fill_color='BuGn',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='매장수 비교'
).add_to(m)
for i in df_vs.index:
sub_long = df_vs.loc[i, "경도"]
sub_lat = df_vs.loc[i, "위도"]
cafes = ["스타벅스", "이디야"]
for cafe in cafes:
cafe_count = df_vs.loc[i, cafe]
gu = df_vs.loc[i, "구"]
tooltip = f"{gu} {cafe} : {cafe_count}"
radius = np.sqrt(cafe_count) * 3
if cafe == "이디야":
color = "blue"
sub_long = sub_long + 0.01
else:
color = "green"
folium.CircleMarker([sub_lat, sub_long],
radius=radius,
color=color,
fill=True,
tooltip=tooltip,
).add_to(m)
m
'python' 카테고리의 다른 글
[python] 소상공인시장진흥공단 상가업소정보로 프랜차이즈 입점분석 (3) (0) | 2023.01.28 |
---|---|
[python] 100 pandas puzzles (0) | 2023.01.27 |
[python] jupyter notebook에서 생성한 folium map 티스토리로 불러오기 (2) | 2023.01.26 |
[python] 소상공인시장진흥공단 상가업소정보로 프랜차이즈 입점분석 (2) (1) | 2023.01.25 |
[python] 소상공인시장진흥공단 상가업소정보로 프랜차이즈 입점분석 (1) (0) | 2023.01.25 |
댓글