셰이프 파일(shp) 데이터의 위도, 경도 및 주소 추출하기
데이터 소개
사용한 데이터
- 사용한 데이터 : 서울 실시간 인구데이터
- 해당 데이터는 서울 주요 116개 장소의 실시간 인구를 확인 가능
- 지역구 컬럼이 없기에 구 별 실시간 인구를 확인하기는 힘듦
- 사이트에서 제공하는 cpg, dbf, prj, shp, shx 데이터를 사용해 지역구 추출
데이터 형태 확인
- geopandas 라이브러리를 활용해 다운로드 받은 데이터의 형태를 확인
- 위도, 경도 데이터는 "POLYGON (( ~ ))" 형태로 존재하는 것을 확인
import geopandas as gpd
D1 = gpd.read_file("./서울시 주요 116장소 영역.shp", encoding='UTF-8')
print(D1.tail())
CATEGORY AREA_CD AREA_NM geometry
공원 POI112 청계산 POLYGON ((127.04946 37.45425, 127.06166 37.439...
공원 POI113 청와대 POLYGON ((126.97924 37.58373, 126.97925 37.583...
발달상권 POI114 북창동 먹자골목 POLYGON ((126.97601 37.56067, 126.97602 37.560...
발달상권 POI115 남대문시장 POLYGON ((126.97605 37.56032, 126.97796 37.560...
발달상권 POI116 익선동 POLYGON ((126.98853 37.57543, 126.99061 37.575...
- POLYGON 데이터는 위도, 경도를 기반으로 이미지가 출력
D1['geometry'][0]
POLYGON 데이터의 위도, 경도 및 주소 추출
라이브러리 및 데이터 가져오기
import geopandas as gpd
from geopy.geocoders import Nominatim
import re
D1 = gpd.read_file("./서울시 주요 116장소 영역.shp", encoding='UTF-8')
지역구 별로 저장하기 위한 딕셔너리 초기화
district= {
"강남구": [],
"강동구": [],
"강북구": [],
"강서구": [],
"관악구": [],
"광진구": [],
"구로구": [],
"금천구": [],
"노원구": [],
"도봉구": [],
"동대문구": [],
"동작구": [],
"마포구": [],
"서대문구": [],
"서초구": [],
"성동구": [],
"성북구": [],
"송파구": [],
"양천구": [],
"영등포구": [],
"용산구": [],
"은평구": [],
"종로구": [],
"중구": [],
"중랑구": [],
"기타": []
}
위도, 경도 데이터를 주소로 반환해주는 함수
- 예시 파라미터 입력 : "127.04946, 37.45425"
def geocoding_reverse(lat_lng_str):
geolocoder = Nominatim(user_agent = 'South Korea', timeout=None)
address = geolocoder.reverse(lat_lng_str)
return address
위도, 경도 및 주소 추출
- POLYGON 데이터를 문자열로 받아와 위도, 경도만 추출 후 각 리스트에 저장
- 해당 POLYGON 중심부의 위도, 경도를 바탕으로 주소 탐색
- 매치되는 지역구에 주요 지역 저장
for d in range(len(D1)):
polygon = str(D1['geometry'][d])
# POLYGON 좌표 문자열에서 좌표 부분만 추출
coordinates = polygon.replace("POLYGON", "").replace(")", "").replace("(", "").split(", ")
# 경도와 위도를 각각 분리하여 리스트에 저장
longitudes = []
latitudes = []
for coord in coordinates:
lon, lat = map(float, coord.split()) # 각 좌표를 float으로 변환
longitudes.append(lon)
latitudes.append(lat)
# 평균 계산
average_longitude = sum(longitudes) / len(longitudes)
average_latitude = sum(latitudes) / len(latitudes)
address = geocoding_reverse(f'{average_latitude}, {average_longitude}')
match = re.search(r'\b([가-힣]{1,3}구)\b', str(address))
if match:
gu = match.group(1)
print(f"{d} : {D1['AREA_NM'][d]}({gu})")
if gu in district.keys():
district[gu].append(D1['AREA_NM'][d])
else:
district["기타"].append(D1['AREA_NM'][d])
else:
print(f"{D1['AREA_NM'][d]} : 구가 포함된 부분을 찾지 못했습니다. | 주소 : {address}")
- 출력 결과
- 서울대공원은 "~구"가 존재하지 않으므로 저장되지 않음 + 서울에 존재하지 않음
...
90 : 남산공원(중구)
91 : 노들섬(용산구)
92 : 뚝섬한강공원(광진구)
93 : 망원한강공원(마포구)
94 : 반포한강공원(서초구)
95 : 북서울꿈의숲(강북구)
96 : 불광천(은평구)
97 : 서리풀공원·몽마르뜨공원(서초구)
98 : 서울광장(중구)
서울대공원 : 구가 포함된 부분을 찾지 못했습니다. | 주소 : 동물원둘레길, 막계동, 과천시, 경기도, 13829, 대한민국
100 : 서울숲공원(성동구)
101 : 아차산(광진구)
102 : 양화한강공원(영등포구)
103 : 어린이대공원(광진구)
104 : 여의도한강공원(영등포구)
...
- 실행 후 딕셔너리
{'강남구': ['강남 MICE 관광특구',
'강남역',
'선릉역',
'신논현역·논현역',
'역삼역',
'가로수길',
'압구정로데오거리',
'청담동 명품거리',
'강남 MICE 관광특구',
'강남역',
'선릉역',
'신논현역·논현역',
'역삼역',
'가로수길',
'압구정로데오거리',
'청담동 명품거리'],
'강동구': ['서울 암사동 유적',
'고덕역',
'천호역',
'광나루한강공원',
'서울 암사동 유적',
'고덕역',
'천호역',
'광나루한강공원'],
...
Reference
'Python' 카테고리의 다른 글
[Python] 특정, 다중 조건으로 리스트 정렬하기 (0) | 2024.11.04 |
---|---|
[Python] 한 줄에 여러 개 입력받기(map, split) (2) | 2024.05.17 |
[Python] 데크(Deque) 개념과 활용 (0) | 2024.05.15 |
[Python] enumerate() 함수 개념과 활용 (0) | 2024.03.30 |
[Python] 람다(Lambda) 함수 개념과 활용 (0) | 2024.03.28 |