import requests
import json
# 서울 행정구역 json raw파일(githubcontent)
r = requests.get('https://raw.githubusercontent.com/southkorea/seoul-maps/master/kostat/2013/json/seoul_municipalities_geo_simple.json')
c = r.content
seoul_geo = json.loads(c)
# 각 구마다 어떻게 구성이 되어있는지 json형태로 확인가능,
#seoul_geo # 일단 너무 길어서 주석처리함
# 서울시 구별 바운더리 시각화
m = folium.Map(
location=[37.52408, 126.9802], # 일단 서울시 용산구의 국립중앙박물관 경도,위도
zoom_start=11,
)
folium.GeoJson(seoul_geo, name='지역구').add_to(m)
#--------Json파일
m # 바운더리 기준으로 표시됨

지도타입 변경
# 위의 지도 테마 변경
m = folium.Map(
location=[37.52408, 126.9802],
zoom_start=11,
tiles='cartodbpositron', # 타일변경 'CartoDB positron' 해도 똑같음
)
folium.GeoJson(seoul_geo, name='지역구').add_to(m)
m

# 서울시 데이터 불러오기
seoul = pd.read_csv('./learn/data20230930/소상공인시장진흥공단_상가(상권)정보_서울_202309.csv')
# 컬럼 확인
print(seoul.columns)
# 필요 컬럼만 발췌
seoul = seoul[['시군구명','상권업종대분류명','상권업종중분류명','위도','경도']]
seoul

# 서울시 업종별('상권업종중분류명') 갯수
seoul.상권업종중분류명.value_counts() # 많은 순에서부터 내림차순

# 서울시 업종별('상권업종중분류명') 내림차순정렬에서 업종명만 발췌
seoul.상권업종중분류명.value_counts().index

# 서울시 업종별('상권업종중분류명') 갯수 시각화
plt.figure(figsize=(5,10))
sns.countplot(y=seoul.상권업종중분류명);

# 서울시 업종별('상권업종중분류명') 갯수 시각화 --> 내림차순
plt.figure(figsize=(10,20))
plt.yticks(fontsize=12)
plt.title('서울시 업종별 갯수(2023년 9월)')
sns.countplot(y=seoul.상권업종중분류명, order=seoul.상권업종중분류명.value_counts().index);

# 상권업종중분류명 컬럼의 앞뒤 공백 제거
seoul['상권업종중분류명'] = seoul['상권업종중분류명'].str.strip()
# '비알코올 ' --> '비알코올'
# 커피/카페 업종('비알코올')만 발췌
seoul.loc[seoul['상권업종중분류명'] == '비알코올']

# 커피/카페 업종('비알코올')만 발췌 후, 자치구별 비교
seoul.loc[seoul['상권업종중분류명'] == '비알코올'].groupby('시군구명')['상권업종대분류명'].count()

# 커피/카페 업종('비알코올')만 발췌 후, 자치구별 '오름차순'비교
seoul.loc[seoul['상권업종중분류명'] == '비알코올'].groupby('시군구명')['상권업종대분류명'].count().sort_values()

# 커피/카페 업종('비알코올')만 발췌 후, 자치구별 '오름차순'비교 시각화
seoul.loc[seoul['상권업종중분류명'] == '비알코올'].groupby('시군구명')['상권업종대분류명'].count().sort_values().plot(kind='bar')

# 커피/카페 업종('비알코올')만 발췌 후, 자치구별 '오름차순'비교 시각화
plt.title('서울시 커피/카피/비알코올 자치구별 수(2023년 9월)')
seoul.loc[seoul['상권업종중분류명'] == '비알코올'].groupby('시군구명')['상권업종대분류명'].count().sort_values().plot(kind='barh');

# 지도 생성
m = folium.Map(
location=[37.52408, 126.9802],
zoom_start=11,
tiles='cartodbpositron',
)
folium.GeoJson(
seoul_geo,
name='지역구'
).add_to(m)
# m

# 클러스터 추가
marker_cluster = MarkerCluster().add_to(m)
# 서울시 커피/카페/비알코올 데이터만 발췌
seoul_coffee = seoul.loc[seoul['상권업종중분류명'] == '비알코올']
# 그 중 위도와 경도만 발췌하여 반복문으로 묶어서, 클러스터에 추가
for lat, lng in zip(seoul_coffee['위도'],seoul_coffee['경도']):
folium.Marker([lat,lng], icon=folium.Icon(color='red')).add_to(marker_cluster)
m

# 서울시 자치구별로 '비알코올'인 업종 갯수 확인
seoul_group_data = seoul.loc[seoul['상권업종중분류명']=='비알코올'].groupby('시군구명')['상권업종중분류명'].count()
seoul_group_data

# 서울시 자치구별로 '비알코올'인 업종 갯수에 따른 색상차이 맵시각화
m = folium.Map( # 지도 셋팅
location=[37.52408, 126.9802],
zoom_start=11,
tiles='cartodbpositron'
)
# Json파일(서울시 자치구별 위도,경도 데이터 추가)
folium.GeoJson(
seoul_geo,
name='지역구',
).add_to(m)
m

참고로 seoul_geo 는 행정구별(강남구,송파구...등) 위도와 경도로 구분해놓은 json파일

# 서울시 행정구역 데이터 seoul_geo 가져와서 대입하기
folium.Choropleth(
geo_data=seoul_geo, # 서울시 행정구역 표기된 json데이터
data = seoul_group_data, # 서울시 자치구별 '비알코올' 업종 갯수
fill_color='YlOrRd',
fill_opacity=0.5, # 투명도 1짙음, 0흐림
line_opacity=0.2,
key_on = 'properties.name', # seoul_geo의 properties 이름 지정 (다른 json파일에서는 properties가 아닐수 있으니 주의)
legend_name = '지역구별 카페 업종 수'
).add_to(m)
m

list(seoul_group_data.quantile([0, 0.25, 0.5, 0.75, 1 ])) # 퍼센트로 4구간 나누어줌
이렇게 하면 [390.0, 614.0, 800.0, 1025.0, 2083.0]
위의 수치값으로 4구간 나뉘어짐
# 위처럼 균등분할이 아닌, 4구간으로 나누어 퍼센트로 시각화
bins = list(seoul_group_data.quantile([0, 0.25, 0.5, 0.75, 1 ]))
m = folium.Map( # 지도 셋팅
location=[37.52408, 126.9802],
zoom_start=11,
tiles='cartodbpositron'
)
# Json파일(서울시 자치구별 위도,경도 데이터 추가)
folium.GeoJson(
seoul_geo,
name='지역구',
).add_to(m)
folium.Choropleth(
geo_data=seoul_geo, # 서울시 행정구역 표기된 json데이터
data = seoul_group_data, # 서울시 자치구별 '비알코올' 업종 갯수
fill_color='YlOrRd',
fill_opacity=0.5, # 투명도 1짙음, 0흐림
line_opacity=0.2,
key_on = 'properties.name', # seoul_geo의 properties 이름 지정 (다른 json파일에서는 properties가 아닐수 있으니 주의)
legend_name = '지역구별 카페 업종 수',
bins = bins
).add_to(m)
m

# HTML 파일로 저장
m.save('map.html')