수달이네 기술 블로그

4. 공공 데이터셋 가져오기 본문

AI공부/머신러닝

4. 공공 데이터셋 가져오기

슬픈 수달이 2025. 11. 26. 23:10

공공데이터셋

https://www.data.go.kr/

해당 공공 데이터셋 사이트에는 다양한 데이터들이 존재한다,

  • excel, csv, json등 파일형식으로 다운로드 하거나 api형태로 실시간 연동도 가능하다.
  • 해당 홈페이지에서 csv파일을 다운로드하여 ipynb파일에서 실행할 수 있다.
import pandas as pd

df = pd.read_csv("data/소상공인시장진흥공단_상가(상권)정보_서울_202510.csv", low_memory=False)
df
  • pandas에서 low_memory를 false로 바꾼다면 각각의 데이터타입을 정확하게 판단할 수 있다.
    • 메모리를 사용하지만 데이터를 한번에 불러오므로

…은 컬럼이 생략된 것이다.

이걸 생략하지 않고 보기 위해서는.

pd.set_option('display.max_column', 40)
  • 해당 옵션 함수를 이용하여 최대 컬럼 수를 내가 원하는 만큼으로 늘릴 수 있다.

산점도

import matplotlib.pyplot as plt

# 산점도 그리기
plt.figure(figsize=(6, 8))  # 그래프 크기 설정
plt.scatter(df['경도'], df['위도'])  # 산점도 그리기
plt.xlabel('경도')  # x축 레이블
plt.ylabel('위도')  # y축 레이블
plt.grid(True)  # 그리드 추가
plt.show()  # 그래프 출력|

scatter를 이용하여 산점도를 그려줄 수 있다.

Seaborn

Python의 데이터 시각화 라이브러리, Matplotlib 위에 구축되어 데이터를 간단하고 쉽게 시각화 할수 있도록 설계

import seaborn as sns
plt.figure(figsize = (10, 12))
sns.scatterplot(data = df, x = '경도', y = '위도', hue = "시군구명")

시군구명에 따라 다양한 색으로 표기 가능하다.(산점도)

  • scatterplot(데이터명, x축, y축, hue(나누기 기준)

Folium

파이썬에서 대화형 지도를 생성할 수 있는 라이브러리(지리데이터 시각화에 최적화

  • 지도 기능을 구현 가능하다.
import folium as fol

map_folium = fol.Map(location = [37.56652479270633, 126.9779129116262], zoom_start=15)

map_folium

마커기능도 이용할 수 있는데,

import folium as fol

map_folium = fol.Map(location = [37.56652479270633, 126.9779129116262], zoom_start=15)
popup = fol.Popup('서울특별시청', max_width = 200)
fol.Marker(location=[37.56652479270633, 126.9779129116262], popup=popup).add_to(map_folium)

map_folium

마커기능도 이용할 수 있는데,

import folium as fol

map_folium = fol.Map(location = [37.56652479270633, 126.9779129116262], zoom_start=15)
popup = fol.Popup('서울특별시청', max_width = 200)
fol.Marker(location=[37.56652479270633, 126.9779129116262], popup=popup).add_to(map_folium)

map_folium

from folium.features import CustomIcon

icon = CustomIcon('data/police-station.png', icon_size=(45, 45))

map_folium = folium.Map(location=[37.56652479270633, 126.9779129116262], zoom_start=15)
popup = folium.Popup('서울특별시청', max_width=200)
folium.Marker(location=[37.56652479270633, 126.9779129116262], popup=popup,
              icon=folium.Icon(icon='star', color='red')).add_to(map_folium)
popup = folium.Popup('덕수궁', max_width=200)
folium.Marker(location=[37.56585320879458, 126.97514572197248], popup=popup,
              icon=folium.Icon(icon='ok', color='pink')).add_to(map_folium)

popup = folium.Popup('서울지방경찰청', max_width=200)
folium.Marker(location=[37.57504045678939, 126.97195576938117], popup=popup,
              icon=icon).add_to(map_folium)

popup = folium.Popup('광화문', max_width=200)
folium.Marker(location=[37.57617987638928, 126.97694467807803], popup=popup).add_to(map_folium)
# CircleMarker(): 원의 범위를 마커로 설정
popup = folium.Popup('내땅', max_width=200)
folium.CircleMarker(location=[37.56999947440024, 126.98228391170936], popup=popup,
              radius=30, color='red', fill_color='#ec4074').add_to(map_folium)
map_folium

  • 위와 같이 다양한 방식으로 팝업 마커를 수정할 수 있다.

위에서 만든 데이터셋을 folium 에 넣기

data = shop_edu_etc_com
edu_map = folium.Map(location = [data['위도'].mean(), data['경도'].mean()], zoom_start= 12)

for i in data.index:
    edu_name = data.loc[i, '상호명'] + '-' + data.loc[i, '도로명주소']
    popup= folium.Popup(edu_name, max_width = 200)
    folium.Marker(location = [data.loc[i, '위도'], data.loc[i, '경도']], popup=popup).add_to(edu_map)
edu_map
  • 반복문을 사용해 위도와 경도를 하나씩 찍어준다.

서울시 열린 데이터 광장

서울시의 openAPI를 넣어줄것이다,.

원하는 데이터 샘플 사이트에 들어가면 인증키 신청이 존재한다. 입력할 것을 넣어주고(이메일은 아무거나)

발급 완료하면

인증키 관리 탭을 눌러, 일반 인증키에서 복사해준다.

다시 원하는 데이터 샘플 사이트에서

http://openapi.seoul.go.kr:8088/(인증키)/json/bikeList/1/5/

해당 링크를 찾은 후 내가 얻은 인증키를 넣어준다.

  • 그러면 json형식의 openAPI를 받아올 준비를 한거다.

해당 쿼리를 살펴보면

json: 제이슨 파일으로

bikeList: 바이크 라는 오픈 api를

1: 1페이지째를

5: 5개 불러온다.

base_url = "<http://openapi.seoul.go.kr:8088/{고유키}/json/bikeList/1/5/>"
response = requests.get(base_url)  

response    # = 정상출력
  • requests를 통해 객체를 얻어오고,
  • 해당 객체를 response객체에 넣어준다.
json_data = response.json()
json_data

# {'rentBikeStatus': {'list_total_count': 5,
#   'RESULT': {'CODE': 'INFO-000', 'MESSAGE': '정상 처리되었습니다.'},
#   'row': [{'rackTotCnt': '15',
#     'stationName': '102. 망원역 1번출구 앞',
#     'parkingBikeTotCnt': '10',
#     'shared': '67',
#     'stationLatitude': '37.55564880',
#     'stationLongitude': '126.91062927',
#     'stationId': 'ST-4'},
#    {'rackTotCnt': '14',
#     'stationName': '103. 망원역 2번출구 앞',
#     'parkingBikeTotCnt': '20',
#     'shared': '143',
#     'stationLatitude': '37.55495071',
#     'stationLongitude': '126.91083527',
#     'stationId': 'ST-5'},
#    {'rackTotCnt': '13',
#     'stationName': '104. 합정역 1번출구 앞',
#     'parkingBikeTotCnt': '18',
#     'shared': '138',
#     'stationLatitude': '37.55073929',
#     'stationLongitude': '126.91508484',
#     'stationId': 'ST-6'},
#    {'rackTotCnt': '5',
#     'stationName': '105. 합정역 5번출구 앞',
# ...
#     'parkingBikeTotCnt': '1',
#     'shared': '8',
#     'stationLatitude': '37.54864502',
#     'stationLongitude': '126.91282654',
#     'stationId': 'ST-8'}]}}
# Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
  • 그리고 json방식으로 해당 데이터를 가져오면 위와 같다.

JSON파일은

  • RESULT: 결과 내용과 메세지를 담고 있다.
  • row: 결과 내용들을 담고 있다.

그러나 JSON파일은 한번에 1000개의 데이터씩만 불러올 수 있으므로 이걸 자동화시키기 위해

def fetch_bike_data():
    base_url = "<http://openapi.seoul.go.kr:8088/{고유키}/json/bikeList/>"
    start = 1
    end = 1000
    step = 1000
    data_frames= []
    while True:
        url = f'{base_url}{start}/{end}/'  #url세팅
        response = requests.get(url)
        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('데이터 없음')
        elif result_code== "ERROR-336":
            print("데이터 요청은 1000건을 넘길수 없습니다")
            break
        else:
            print(f"알 수 없는 오류: {result_code}")
            break
        start += step
        end += step
    if data_frames:
        final_df = pd.concat(data_frames, ignore_index = True)      #인덱스를 제외하고 데이터프레임을 붙여줘
        return final_df
df = fetch_bike_data()
df

위와 같이 코드를 짰다.

  1. base_url: 키와 코드를 담은 url 처음 줄과 끝줄을 표시하는 내용은 제외
  2. start, end, step:에 코드를 넣어둔 후
  3. data_frames = []:에 찾은 데이터를 모두 넣는다.

while문

  1. url에 완성된 url을 만들어 넣는다.
  2. 이곳에서 requests를 이용해 내용을 얻어오는데,
  3. rent_bike_status: json내용을 넣고
  4. result_code: 얻어온 내용에서 받아온 status_code, 얻은 결과를 찾는다.
  5. 키에 따라 오류를 설정해준다.
  6. 제대로 찾았을 경우(INFO-000일 경우): dataframe형식으로 만들어준 후 data_frames 변수에 저장해준다.
  7. 마지막엔 start와 end를 step만큼 증가시켜준다.
  8. 그리고 while문이 break에 의해 끝났다면, data_frames를 index제외, 반환해준다.

얻어온 결과는 데이터프레임 형식이므로 위와 같이 보인다.

이제 위 결과를 folium으로 맵에 넣어줄건데,

bike_map = folium.Map(location=[df['stationLatitude'].mean(), 
                                df['stationLongitude'].mean()],
                                zoom_start = 12)
for index,data in 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

위처럼 표시될 수 있다.

'AI공부 > 머신러닝' 카테고리의 다른 글

강화학습 기본 개념  (0) 2025.12.01
5. selenium을 이용한 크롤링  (1) 2025.11.26
참고) 머신러닝/딥러닝 모델별 장단점 표  (0) 2025.11.25
3. matplot  (0) 2025.11.19
2. Pandas  (1) 2025.11.17