Prologue
오늘한 것: 구간별 좌표 리스트 출력, 신호등 좌표와 매핑, , 엔터티 구성 및 ERD, Postgre SQL 3문제 / 내가 실행해봤던 것들, 작은 것들을 꾸준히 남기자..!
구간별 좌표 리스트 출력
신호등 데이터 확보
데이터
- 이름: 구미시 신호등 표준 데이터
- 설명: 『도로교통법』에 따라 교통안전확보 또는 원활한 교통흐름을 제어하기 위해 진행, 정지, 주의, 회전 등을 지시하도록 설치된 신호등에 대한 정보
- 제공기관: 구미시청
- 제공방식: CSV 다운로드
- 수정일자: 2025-03-10
- 관리부서 전화번호: 054-480-2573
데이터 EDA
소셜포커스, 양우일, 적색점멸ㆍ황색점멸… 신호등에 숨은 비밀은?, 2020.03
구간의 여러 개 좌표와 신호등의 좌표를 매핑할 수 있을까?
가능하다
신호등과 구간 데이터를 GeoDataFrame으로 만들기
- 구간은 Linestring 좌표 클래스로 만들기
- 신호등은 Point 좌표 클래스로 만들기
- 각각의 클래스를 담은 DF로 만들기
- segment의 행을 돌면서 signal의 좌표가 있는지 찾기
segment에 있는 좌표들을 기준으로 10m(설정값) 범위를 포함하는 영역을 생성
구간의 좌표를 Linestring 클래스로 만들기
구간의 좌표를 TMAP API로 받기
- 1개의 구간의 출발점과 도착점을 전달
- 출발점부터 도착점까지 Point와 Linestring geometry 객체의 좌표 값이 'coordinates'로 전달된다
- 아래의 코드를 통해 geodata가 포함된 구간 리스트 만들기
# 값을 얻은 구간 리스트 선언
get_route=[]
api_cnt = 0
print(f"get_route_cnt: {len(get_route)}")
print(f"api_cnt: {api_cnt}")
import requests
import json
res = [] # api 값이 담긴 df가 담기는 리스트
already = 0 # 이미 있는 리스트가 for문 돌아간 횟수
not_200 = 0 # 정상적이지 않은 api 호출 수
# DF의 좌표 뽑기
for route in route_xy.구간이름.values[1394:1894]:
# 새로운 route인지 확인
if route in get_route:
already += 1
continue
# 좌표 변수에 담기
lon_a = route_xy[route_xy.구간이름 == route].iloc[0]['경도_A']
lat_a = route_xy[route_xy.구간이름 == route].iloc[0]['위도_A']
lon_b = route_xy[route_xy.구간이름 == route].iloc[0]['경도_B']
lat_b = route_xy[route_xy.구간이름 == route].iloc[0]['위도_B']
# API에 좌표 입력 후 데이터 받기
url = "https://apis.openapi.sk.com/tmap/routes"
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"appKey": appkey1
}
data = {
"startX": lon_a,
"startY": lat_a,
"endX": lon_b,
"endY": lat_b,
"totalValue": 1
}
api_cnt += 1
response = requests.post(url, headers=headers, json=data)
# 확인 작업
if response.status_code != 200:
not_200 += 1
continue
else:
# 실행 작업
data = json.loads(response.text)
coords=[]
# coords에 좌표 추가
for nums in range(len(data['features'])):
if type(data['features'][nums]['geometry']['coordinates'][0]) == float:
coords.append(data['features'][nums]['geometry']['coordinates'])
else:
new_data = data['features'][nums]['geometry']['coordinates']
for datas in new_data:
coords.append(datas)
# df로 변환
segments = gpd.GeoDataFrame({
'구간이름': [route],
'geometry': [LineString(coords)]
}, geometry='geometry', crs='EPSG:4326')
res.append(segments)
get_route.append(route)
print(f"already: {already}")
print(f"not_200: {not_200}")
# 새로운 df들 하나로 만들기
df = pd.concat(res, ignore_index=True)
df.nunique()
# 기존 geo_df 와 새로운 df 합치기
df1 = pd.concat([df, df1], ignore_index=True)
# 혹시 모를 그 전 데이터 저장
df2 = df1.copy()
display(df2, df2.nunique())
신호등 데이터 Point로 만들기
- 2025년 2월 20일 업데이트 csv 읽기
- 신호등 경도, 위도를 Point 클래스로 만들기
신호등과 구간 데이터 매핑하기
매핑하는 함수 정의: 구간의 모든 행을 돌면서 신호등의 모든 행에서 반경 10m 이내의 신호등을 찾음
구간: 여러 개의 좌표로 이루어진 Linestring, 신호등은 한 개의 좌표로 이루어진 Point
따라서 여러 개의 신호등이 구간의 반경 10m에 들어올 수 있음
- 함수 사용: 구간이름과 그에 포함된 신호등 ID가 매핑됨
- 17분 걸림.. 시간 단축할 수 있게 구간이름을 숫자 타입으로 바꿔야 할 듯
- 신호등 데이터 EDA를 통해 올바르게 매핑되는지 확인할 필요 있음
모델링
배경
DF가 7개 정도로 많음
이상치인지 확인하기 위해 DF에 흩어진 정보를 조회할 일이 많은데 merge하기 힘듦..
요구사항
내가 맡은 업무 중 어떤 업무를 데이터화하여 모델링할 것인지 파악
- 사용자 식별: 본인
- 요구사항: A버스가 A정류장에 00시00분에 도착할 예정임을 예측할 수 있게 이와 관련한 데이터를 구축
- DB 용도: 엔터티 정의, 예상 시간 만들어지는 과정 시각화, 여러 테이블간의 조인 용이하게 하기
- 모델링 할 데이터: 버스 도착시간 예측을 위해 필요한 데이터(버스, 정류장, 도착시간 등)
개념적 데이터 모델링
일의 데이터 간의 관계를 구상
- 핵심 엔터티 도출
버스(노선)
정류장
구간(도로상황) - ERD 작성
- 버스와 정류소간의 M:N 관계를 해소하기 위해 경유 정류소 엔터티 추가
- 경유 정류소별 도착 시간을 예측하기 위해 구간 엔터티 추가
논리적 데이터 모델링
더 구체화해서 업무 중심의 데이터 모델(표 형태) 만들기
- Key, 속성, 관계 표시
- 정규화 수
물리적 데이터 모델링
DB 선택, 실제 테이블 만드는 작업을 SQL 코딩을 통해 수행
- DB 개체 정의
- 테이블 및 인덱스 설계
'Today I Learned' 카테고리의 다른 글
[TIL] 25.03.20 구미 정류소 좌표 데이터 다시 정리 (0) | 2025.03.20 |
---|---|
[TIL] 25.03.19 노선, 좌표 데이터 무결성 확인 (0) | 2025.03.19 |
[TIL] 25.03.15 구미버스 도착시간 데이터 요청 (0) | 2025.03.15 |
[TIL] 25.03.13 API로 불러온 데이터 하나로 합치기 (0) | 2025.03.13 |
[TIL] 25.03.12 버스 로그 데이터로 구간별 걸리는 시간 구하기 (0) | 2025.03.12 |