💡대전광역시 서구 일반음식점 현황 분석
공공 데이터 포털에서 위도, 경도 지도 데이터를 포함하는 csv 파일을 Streamlit에서 folium 라이브러리를 활용하여 시각화하고, 분석해 보도록 하자.
Folium 라이브러리
Folium은 지리 공간 데이터를 시각화하는 데 사용되는 Python 라이브러리이다.
leaflet.js 기반으로 이루어졌으며, 시각화에 활용할 수 있는 OpenStreetMap, Mapbox, Stamen과 같은 지도 이미지를 제공한다. 자세한 내용은 아래 공식 도큐먼트에서 확인할 수 있다.
https://python-visualization.github.io/folium/latest/
라이브러리 설치하기
pip install streamlit streamlit_folium folium
위도 경도가 들어 있는 지도 데이터를 시각화하기 위해 먼저 필요한 라이브러리를 설치해야 한다.
VS Code 터미널을 열고, 가상 환경에 접속하여 streamlit, streamlit_folium, folium 라이브러리를 설치한다.
가상 환경 접속하기
가상 환경에 접속하는 방법은 위 글을 참고한다.
csv 파일 추가하기
https://www.data.go.kr/data/15008957/fileData.do
다음으로 해당 스크립트 파일이 있는 디렉터리에 "대전광역시 서구 일반음식점 현황.csv" 파일을 추가한다.
이때 다른 데이터로 지도 데이터를 표시하려면 이처럼 위도, 경도 데이터가 있는 공공 데이터를 찾아 가져오면 된다.
Streamlit 실행하기
지도 시각화 스크립트 작성하기
import streamlit as st
from streamlit_folium import folium_static
import folium
from folium.plugins import MarkerCluster
import pandas as pd
st.title("대전광역시 서구 일반음식점 현황")
df = pd.read_csv("대전광역시 서구 일반음식점 현황.csv", encoding='ansi')
st.dataframe(df, height=200)
df[["lat","lon"]] = df[["위도","경도"]]
m = folium.Map(location=[36.350412, 127.384548], zoom_start=13)
marker_cluster = MarkerCluster().add_to(m)
for idx, row in df.iterrows():
folium.Marker(
location=[row["lat"], row["lon"]],
popup=row["업소명"],
).add_to(marker_cluster)
folium_static(m)
이 코드는 Streamlit을 사용하여 대전광역시 서구의 일반음식점 현황을 지도로 시각화하는 스크립트이다.
요약하면 라이브러리를 import 하고 데이터를 처리하여 지도에 표시한다.
1. 라이브러리 import
import streamlit as st
from streamlit_folium import folium_static
import folium
from folium.plugins import MarkerCluster
import pandas as pd
streamlit 및 folium과 관련된 라이브러리들을 import한다.
2. csv 파일 읽기
df = pd.read_csv("대전광역시 서구 일반음식점 현황.csv", encoding='ansi')
대전광역시 서구 일반음식점 현황.csv 파일을 읽어 들인다.
encoding='ansi' 옵션은 CSV 파일이 ANSI로 인코딩 되어 있는 경우에 사용한다.
3. 데이터프레임 생성
st.dataframe(df, height=200)
df[["lat","lon"]] = df[["위도","경도"]]
st.dataframe() 함수를 사용하여 데이터프레임을 Streamlit 앱에 표시한다. 이때 height=200 옵션은 표의 높이를 조정하였으며, 데이터프레임에 위도(lat)와 경도(lon) 열을 새로운 열로 추가했다.
4. 지도 초기 위치 설정
m = folium.Map(location=[36.350412, 127.384548], zoom_start=13)
Folium을 사용하여 새로운 지도를 만들고, 시작 위치와 확대 정도를 설정한다.
5. MarkerCluster 생성
marker_cluster = MarkerCluster().add_to(m)
MarkerCluster를 생성하여 지도에 추가한다. 이는 여러 마커를 그룹화하여 클러스터로 표시해 준다.
6. 마커를 클러스터에 추가
for idx, row in df.iterrows():
folium.Marker(
location=[row["lat"], row["lon"]],
popup=row["업소명"],
).add_to(marker_cluster)
folium_static(m)
데이터프레임을 반복하면서 각 음식점의 위치에 대한 마커를 만들고 클러스터에 추가한다.
folium_static() 함수를 사용하여 Folium 지도를 Streamlit 앱에 표시하였다.
지도 시각화 스크립트 실행하기
streamlit run daejeon_seo_general_restaurant.py
Python 파일 "daejeon_seo_general_restaurant.py"을 생성하고, 해당 위치에 지도 시각화 코드를 작성하였다.
이 파일을 터미널에서 run 명령어를 통해 웹 애플리케이션으로 실행하면 된다.
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbc in position 0: invalid start byte
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbc in position 0: invalid start byte
Traceback:
File "C:\Class\code\streamlit\streamlit_env\lib\site-packages\streamlit\runtime\scriptrunner\script_runner.py", line 535, in _run_script
exec(code, module.__dict__)
File "C:\Class\code\streamlit\streamlit_env\daejeon_seo_general_restaurant.py", line 9, in <module>
df = pd.read_csv("대전광역시 서구 일반음식점 현황.csv")
File "C:\Class\code\streamlit\streamlit_env\lib\site-packages\pandas\io\parsers\readers.py", line 1024, in read_csv
return _read(filepath_or_buffer, kwds)
File "C:\Class\code\streamlit\streamlit_env\lib\site-packages\pandas\io\parsers\readers.py", line 618, in _read
parser = TextFileReader(filepath_or_buffer, **kwds)
File "C:\Class\code\streamlit\streamlit_env\lib\site-packages\pandas\io\parsers\readers.py", line 1618, in __init__
self._engine = self._make_engine(f, self.engine)
File "C:\Class\code\streamlit\streamlit_env\lib\site-packages\pandas\io\parsers\readers.py", line 1896, in _make_engine
return mapping[engine](f, **self.options)
File "C:\Class\code\streamlit\streamlit_env\lib\site-packages\pandas\io\parsers\c_parser_wrapper.py", line 93, in __init__
self._reader = parsers.TextReader(src, **kwds)
File "parsers.pyx", line 574, in pandas._libs.parsers.TextReader.__cinit__
File "parsers.pyx", line 663, in pandas._libs.parsers.TextReader._get_header
File "parsers.pyx", line 874, in pandas._libs.parsers.TextReader._tokenize_rows
File "parsers.pyx", line 891, in pandas._libs.parsers.TextReader._check_tokenize_status
File "parsers.pyx", line 2053, in pandas._libs.parsers.raise_parser_error
UTF-8로 디코딩하려고 시도했지만 올바르지 않은 바이트가 있어서 오류가 발생하였다.
df = pd.read_csv("대전광역시 서구 일반음식점 현황.csv", encoding='ansi')
파일을 올바른 인코딩으로 읽어와야 하는데, 이 경우에는 파일의 인코딩이 UTF-8이 아닐 가능성이 있다.
현재 csv 파일이 ANSI로 인코딩 되어 있는 것으로 보이므로, 인코딩 형식을 수정하였다.
지도 데이터 시각화 결과
성공적으로 대전광역시 서구 일반음식점 현황을 지도로 시각화하였다.
클러스터 기능을 활용하여 음식점이 어떤 지역에 집중 분포되어 있는지를 확인할 수 있으며, 이를 통해 특정 지역에 음식점이 밀집해 있음을 한눈에 파악할 수 있다.
어떤 행정동에 음식점이 분포되어 있을까?
정부대전청사 근처 둔산동 외에도 용문동, 괴정동, 길마동, 가수원동, 관저동에 특히 일반 음식점이 집중 분포되어 있음을 확인했다. 이러한 결과는 해당 지역이 상대적으로 음식점 경쟁이 치열한 지역임을 시사한다.
그러나 이러한 현상이 발생한 이유에 대한 명확한 해석을 위해서는 주택 데이터나 유동 인구 데이터와 같은 추가적인 정보를 함께 고려해야 할 것으로 보인다. 관련 데이터를 종합적으로 분석함으로써 더 의미 있는 결과를 도출할 수 있다.
지도를 확대, 축소할 수 있으며, 마커를 클릭하면 해당 음식점의 업소명이 나타난다.
참고 자료
[이론4] 지도 그리기, 엘리스코딩, 2024.02.09.