1. 서울 열린데이터 광장
서울 열린데이터 광장(Seoul Open Data Plaza)은 서울시에서 운영하는 공공데이터 개방 플랫폼입니다. 시민, 연구자, 기업 등이 서울시에서 생성한 다양한 공공데이터를 자유롭게 활용할 수 있도록 제공하고 있습니다. 이를 통해 데이터 기반의 창의적인 아이디어와 혁신을 촉진하며, 시민들의 정보 접근성을 높이고 공공서비스를 개선하는 데 기여하고 있습니다.
2. 서울시 공공자전거 실시간 대여정보
- 인증키를 발급 받습니다.
- "서울시 공공자전거 실시간 대여정보" 를 검색합니다.
필요한 모듈 import
import requests
import folium
import json
import pandas as pd
import warnings
warnings.filterwarnings('ignore') #warning 감추기
응답 데이터를 JSON형태로 파싱
base_url = 'http://openapi.seoul.go.kr:8088/5465637658746c6139374b63447951/json/bikeList/1/2/'
response = requests.get(base_url)
# print(response)
json_data = response.json()
json_data
아래와 같이 데이터를 불러올 경우 값이 없거나 키가 없으면 KeyError가 발생하게된다.
json_data["rentBikeStatus"]["RESULT"]["CODE"]
#값이 없으면 바로 에러남 그래서 try catch 써야함
개선된 접근법: dict.get() 사용
dict.get() 메서드를 사용하면 키가 없을 경우 기본값을 반환하도록 설정할 수 있습니다. 이렇게 하면 코드가 더 간결하고 안전해집니다:
json_data.get('rentBikeStatus',{}).get("RESULT", {}).get("CODE", "")
#값이 없어도 에러 안남
서울시 공공자전거 API 데이터 가져오는 함수 설정
import time
def fetch_bike_data():
base_url = 'http://openapi.seoul.go.kr:8088/5465637658746c6139374b63447951/json/bikeList/'
start = 1
end = 1000
step = 1000
data_frames = []
while True:
url = f'{base_url}{start}/{end}/'
response = requests.get(url)
time.sleep(1)
if response.status_code != 200:
print(f'Status Code: {response.status_code}')
break
json_data = response.json()
try:
rent_bike_status = json_data['rentBikeStatus']
result_code = rent_bike_status['RESULT']['CODE']
except KeyError:
print('json 오류')
break
if result_code == 'INFO-200':
print('데이터 없음')
break
elif result_code == 'INFO-000':
print(f'시작{start}, 끝{end}')
try:
bike_data = rent_bike_status['row']
if bike_data:
df = pd.DataFrame(bike_data)
data_frames.append(df)
except KeyError:
print('데이터를 찾을 수 없음')
else:
print(f'result_code: {result_code}')
break
start += step
end += step
if data_frames:
final_df = pd.concat(data_frames, ignore_index=True)
return final_df
else:
return pd.DataFrame()
코드 구조 및 흐름
기본 설정
base_url = 'http://openapi.seoul.go.kr:8088/5465637658746c6139374b63447951/json/bikeList/'
start = 1
end = 1000
step = 1000
data_frames = []
- base_url: 서울시 공공자전거 API 엔드포인트.
- start: 데이터를 가져오는 시작 인덱스.
- end: 데이터를 가져오는 종료 인덱스.
- step: 한 번에 가져올 데이터의 범위(여기서는 1,000개).
- data_frames: 가져온 데이터를 임시로 저장할 DataFrame 리스트.
데이터를 가져오는 반복문
while True:
url = f'{base_url}{start}/{end}/'
print(f"Fetching data from: {url}")
response = requests.get(url)
time.sleep(1) # 요청 간 간격 유지
- URL 생성: API 호출을 위한 URL을 start와 end로 동적으로 생성.
- requests.get: API 요청을 보내 데이터 가져오기.
- time.sleep(1): API 호출 간 1초 대기(서버 과부하 방지 및 Rate Limit 준수).
응답 코드 확인
if response.status_code != 200:
print(f"HTTP Error: Status Code {response.status_code}")
break
HTTP 상태 코드가 200이 아니면 오류를 출력하고 반복문 종료.
JSON데이터 파싱 및 오류 처리
try:
json_data = response.json()
rent_bike_status = json_data['rentBikeStatus']
result_code = rent_bike_status['RESULT']['CODE']
except KeyError:
print("JSON Parsing Error: Key not found")
break
- JSON 데이터 파싱: API 응답 데이터를 JSON 형식으로 변환.
- rentBikeStatus: 자전거 대여소 관련 데이터를 포함하는 JSON의 최상위 키.
- KeyError 처리: JSON 구조가 예상과 다를 경우 예외 처리.
결과 코드에 따른 처리
if result_code == 'INFO-200':
print("No more data available.")
break
elif result_code == 'INFO-000':
print(f"Fetching data: Start={start}, End={end}")
- INFO-200: 데이터가 더 이상 없는 경우 반복문 종료.
- INFO-000: 데이터가 정상적으로 있는 경우 처리.
데이터 저장
try:
bike_data = rent_bike_status['row']
if bike_data:
df = pd.DataFrame(bike_data)
data_frames.append(df)
else:
print("Empty bike data received.")
break
- row: 대여소 데이터를 포함하는 리스트.
- pd.DataFrame: 데이터를 pandas.DataFrame으로 변환하여 저장.
- 빈 데이터 처리: row가 비어 있으면 반복문 종료.
인덱스 증가
start += step
end += step
다음 페이지의 데이터를 가져오기 위해 start와 end 값을 증가
최종 데이터프레임 반환
if data_frames:
final_df = pd.concat(data_frames, ignore_index=True)
return final_df
else:
print("No data collected.")
return pd.DataFrame()
- 여러 페이지에서 가져온 데이터를 하나의 DataFrame으로 결합.
- 데이터가 없는 경우 빈 DataFrame 반환.
실행 흐름
- API를 호출하여 한 번에 최대 1,000개의 데이터를 가져옵니다.
- 응답 상태 코드와 결과 코드를 확인하여 데이터가 유효한지 판단합니다.
- 데이터를 가져와 pandas.DataFrame으로 변환 후 저장합니다.
- 데이터가 더 이상 없으면 반복문을 종료합니다.
- 모든 데이터를 합쳐 하나의 DataFrame으로 반환합니다.
실행
bike_data_df = fetch_bike_data()
bike_data_df
- 코드 결과
- 시작1, 끝1000
- 시작1001, 끝2000
- 시작2001, 끝3000
- json 오류
데이터 프레임 잘 만들어진거 확인했으니까 데이터의 info를 확인해보도록 하자
bike_data_df.info()
info를 확인해 보니 null값은 따로 없다 전부 object타입이다
info로 확인해본 콜럼은 다음과 같다
'''
rackTotCnt 거치대개수
parkingBikeTotCnt 자전거주차총건수
shared 거치율
stationLatitude 위도
stationLongitude 경도
stationId 대여소ID
stationName 대여소이름
'''
bike_data_df.columns
데이터는의 shape를 확인해 보았다
bike_data_df.shape는 pandas.DataFrame 객체의 행(row)과 열(column)의 개수를 튜플 형태로 반환한다
bike_data_df.shape
#(2711, 7)
총 2711개의 데이터가 있고 콜럼은 7개이다
folium map활용하기
folium map를 활용하기 위해 위도와 경도 열의 데이터를 object타입이 아닌 float 타입으로 변환한 뒤 데이터 프레임 정보를 출력하는 과정이다.
#위경도를 folium맵에 찍기 위해서 float 타입으로 바꿔줌
bike_data_df['stationLatitude'] = bike_data_df['stationLatitude'].astype(float)
bike_data_df['stationLongitude'] = bike_data_df['stationLongitude'].astype(float)
bike_data_df.info()
지도 출력하기
bike_map = folium.Map(location=[bike_data_df['stationLatitude'].mean(),
bike_data_df['stationLongitude'].mean()], zoom_start=12)
#iterrows : 데이터프레임의 메서드 Pandas 데이터프레임에서 행을 반복(iterate)하면서 해당 행의 인덱스와 데이터를 반환하는 메서드입니다. 이를 통해 데이터프레임의 각 행에 접근하고, 행별로 작업을 수행할 수 있음
for index, data in bike_data_df.iterrows():
popup_str = '{} 자전거주차총건수:{}대'.format(
data['stationName'], data['parkingBikeTotCnt']
)
popup = folium.Popup(popup_str, max_width=600)
folium.Marker(location=[data['stationLatitude'], data['stationLongitude']],
popup=popup).add_to(bike_map)
bike_map
결과
- 지도에는 모든 대여소의 위치가 마커로 표시됩니다.
- 마커를 클릭하면 팝업 창이 열리며, 대여소 이름과 현재 주차된 자전거 수를 확인할 수 있습니다.
코드설명
지도 생성
bike_map = folium.Map(location=[bike_data_df['stationLatitude'].mean(),
bike_data_df['stationLongitude'].mean()], zoom_start=12)
- folium.Map: Folium 지도를 생성하는 메서드입니다.
- location: 지도 중심 좌표입니다. 여기서는 bike_data_df의 stationLatitude(위도)와 stationLongitude(경도) 평균값을 사용하여 중심 위치를 설정합니다.
- zoom_start=12: 지도의 초기 확대 수준을 설정합니다. 값이 작을수록 멀리서 보이고, 값이 클수록 확대됩니다.
데이터 프레임 행 반복 (iterrows)
for index, data in bike_data_df.iterrows():
bike_data_df.iterrows(): bike_data_df 데이터프레임의 각 행을 반복합니다.
- index: 각 행의 인덱스 값.
- data: 현재 행의 데이터를 포함한 시리즈 객체.
팝업 문자열 생성
popup_str = '{} 자전거주차총건수:{}대'.format(
data['stationName'], data['parkingBikeTotCnt']
)
- data['stationName']: 현재 대여소의 이름.
- data['parkingBikeTotCnt']: 현재 대여소에 주차된 자전거 수.
- popup_str: 대여소 이름과 주차된 자전거 수를 포함한 문자열을 생성합니다. 예:
- 시청역 1번 출구 자전거주차총건수:3대
팝업 생성
popup = folium.Popup(popup_str, max_width=600)
folium.Popup: 팝업 창을 생성합니다.
- popup_str: 팝업에 표시할 내용.
- max_width=600: 팝업의 최대 너비를 설정합니다.
마커 추가
folium.Marker(location=[data['stationLatitude'], data['stationLongitude']],
popup=popup).add_to(bike_map)
- folium.Marker: 지도에 마커(위치 표시)를 추가합니다.
- location: 마커의 위치로, 위도(stationLatitude)와 경도(stationLongitude)를 사용합니다.
- popup: 마커를 클릭했을 때 나타날 팝업 창.
- .add_to(bike_map): 생성된 마커를 bike_map에 추가합니다.
'인공지능 > 데이터분석' 카테고리의 다른 글
커피 프랜차이즈의 입점전략 - 스타벅스와 타 커피 프랜차이즈 데이터 분석 (2) | 2025.01.29 |
---|---|
커피 프랜차이즈의 입점전략 - 스타벅스 정보 크롤링 (0) | 2025.01.24 |
소상공인시장진흥공단_상가정보 데이터셋 (4) | 2025.01.17 |
online Retail 데이터셋 - 캐글 (0) | 2025.01.17 |
Matplotlib (2) | 2025.01.17 |