Open API

[Python] 공공데이터 가져오기 (공공데이터포털 - 전국 응급의료기관 정보)

Jerry_K 2024. 3. 27. 22:03

📚공공데이터 활용하기

공공데이터를 사용해서 할 수 있는 것은 정말 많다. 

공공데이터 기반 웹/앱 서비스도 가능하다.

 

그래서 이번 포스팅은 공공데이터를 가져와서, 

내가 원하는 정보를 출력하는 것 까지를 목표로 한다.

 

 


📖 공공데이터 가입/신청 

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

 

공공데이터 포털

국가에서 보유하고 있는 다양한 데이터를『공공데이터의 제공 및 이용 활성화에 관한 법률(제11956호)』에 따라 개방하여 국민들이 보다 쉽고 용이하게 공유•활용할 수 있도록 공공데이터(Datase

www.data.go.kr

 

 

공공데이터 포털에 들어가서 회원가입을 한다.

그리고 원하는 데이터를 검색하고 찾는다. 

 

https://www.data.go.kr/data/15000563/openapi.do

 

국립중앙의료원_전국 응급의료기관 정보 조회 서비스

전국 응급의료기관 정보를 조회하기 위한 서비스로서 실시간 응급실 가용병상정보 및 중증질환 수용가능정보, 위치정보등을 조회할 수 있다.

www.data.go.kr

 

지금 이 포스팅에서는  "국립중앙의료원_전국 응급의료기관 정보 조회 서비스"  데이터를 사용 할 것이다 .

데이터를 사용 하려면 활용 신청을 해야하는데, 해당 데이터에 들어가 활용신청을 하면 바로 승인이 된다. 

 

 


📖 신청한 공공데이터 살펴보기

 

승인 신청이 완료되면, 활용신청 현황에 이렇게 표시가 된다.

 

 

 

 

"오픈 API 상세" 에서 내가 신청한 데이터를 살펴보자.

목록을 보니 "응급실 실시간 가용병상정보"  부터 "응급실 및 중증질환 메시지 조회" 까지 데이터를 구할 수 있다. 

 

 

 

그리고 바로 밑에 요청변수를 봐보자 . 

주소(시도) / 주소(시군구) 파라미터는 필수이고, 나머지는 옵션인 것을 확인 할 수 있다.

 

 

 

출력하는 값들을 보니, 정보가 꽤 많이 출력되는 것을 알 수 있다.

여기에서 내가 필요한 값들을 찾아두면 된다.

 

 

 

이번에는 샘플코드를 살펴보자. 

해당 데이터를 가져오기 위해 파이썬을 쓸 것이기 때문에 파이썬 코드의 예시를 살펴본다.

 


📖 신청한 공공데이터 가져오기

import requests
import pandas as pd 
import xmltodict
encoding = "ENCODING KEY"  # 클라이언트가 사용하는 key
decoding = "DECODING KEY"  # 서버가 사용하는 key
url = 'http://apis.data.go.kr/B552657/ErmctInfoInqireService/getEmrrmRltmUsefulSckbdInfoInqire'

params ={'serviceKey' : decoding,
         'STAGE1' : '서울특별시',
         'STAGE2' : '강남구',
         'pageNo' : '1',
         'numOfRows' : '10' }

response = requests.get(url, params=params)

 

샘플 코드 기반으로 만든 (응급실 실시간 가용병상정보 조회) 코드이다.  

 

다른 목록의 데이터를 가져오고 싶으면, 

그 데이터의 url과  파라미터들을 기반으로 수정하면 된다.

 

dic = xmltodict.parse(response.content)

 

OpenAPI 정보에 데이터 포맷을 보면 , 해당 데이터는 XML 형식인 것을 알 수 있다.

xmltodict.parse()  함수를 사용해서  response.content를 딕셔너리 형태로 바꿔주었다.

 

이제 딕셔너리 형태가 되었으니, 내가 원하는 Key의 value값을 인덱싱하여 가져오면 된다,

 

df = pd.read_xml(response.text, xpath='//item')

 

(🔎  response를 이렇게 데이터프레임으로도 쉽게 나타낼 수 있다. )

 


📖  전국 시도군 병원 이름 출력하기

방금 위에서 출력한 병원은 "서울특별시"의 "강남구" 병원 밖에 없다. 

포스팅의 목표는 전국 시도군 병원 이름을 모두 출력하는 것이다.

 

시도정보.csv
0.01MB
시도코드_법정동기준.xlsx
0.01MB

 

 

내가 원하는대로 출력을 하려면 전국 시도의 정보가 있어야 한다.

우선, 위의 법정동 기둥 시도 정보 파일들을 다운로드 하자. 

 

df = pd.read_csv("./시도정보.csv")
tmp = pd.read_excel("./시도코드_법정동기준.xlsx")

 

 

그리고 해당 경로에 맞춰 출력을 해보면, 위와 같은 데이터프레임이된다.

 

 

💡 필수 전처리

1. 시도코드_법정동 컬럼을 CTPRVN_CD 형태로 변환
2. CTPRVN_CD을 기준으로 시도코드_법정동과 merge
3. merge된 데이터 프레임에서 시도와  SIG_KOR_NM만 따로 추출 

 

원하는 데이터 값들을 출력하기 위해서는 전처리가 필요하다.

 

 

tmp["시도코드_법정동"] = tmp["시도코드_법정동"].astype(str)
tmp["시도코드_법정동"] = tmp["시도코드_법정동"].apply(lambda x : x[:2])

 

 

"시도코드_법정동" 컬럼이 int 형으로 되어있어서  문자형으로 바꿔줬다.

그리고 apply 함수로 각각의 행들이  lambda 함수에 적용되도록 해주었다. 

위의 lambda 함수는 문자열 첫번째,두번째 자리만 반환하는 함수이다. 

 

 

df["CTPRVN_CD"] = df["CTPRVN_CD"].astype(str)
df = pd.merge(df,tmp,left_on="CTPRVN_CD", right_on="시도코드_법정동",how="left")

 

"CTPRVN_CD" 컬럼 또한 int 형으로 되어있어서 문자형으로 바꿔줬다. 

 

"시도코드_법정동" 컬럼명을 "CTPRVN_CD" 로 바꿔줘도 되지만, 

내가 필요한 컬럼은 "시도"와  "SIG_KOR_NM"이므로 컬렁명 변경없이 merge 해주었다.

 

 

new_df = df[["시도","SIG_KOR_NM"]]

 

"시도"와  "SIG_KOR_NM"만 따로 분리해 새로운 데이터 프레임을 만들었다. 

 

 

new_df[new_df["시도"].isna()]

 

그리고 결측값이 있나 확인을 해보았는데,  세종특별자치시가 문제가 되었다. 

따로 확인해본 결과,  "세종특별자치시"에 시도는 공백으로 배치해도 문제가 없었다.

 

new_df.iloc[74,:]["시도"] = ""
new_df[new_df["시도"].isna()]

 

 

세종특별자치시의 결측치를 공백으로 변경하고, 다시 결측치를 확인해보았다.

이제는 결측치가 완전히 사라진 것을 볼 수 있다 . 

 

 

💡 전국 병원 이름 출력 

url = 'http://apis.data.go.kr/B552657/ErmctInfoInqireService/getEmrrmRltmUsefulSckbdInfoInqire'
for i in range(len(new_df)) :
    params ={'serviceKey' : decoding,
             'STAGE1' : new_df.iloc[i,0],
             'STAGE2' : new_df.iloc[i,1],
             'pageNo' : '1',
             'numOfRows' : '10' }

    response = requests.get(url, params=params)
    dic = xmltodict.parse(response.content)
    
    print(f"{i+1}. {new_df.iloc[i,0]} {new_df.iloc[i,1]}")  # 시도명 출력
    
    try :
        # item의 개수가 1개 이상인 경우 
        for j in range(len(dic["response"]["body"]["items"]["item"])):  
            print("\t"+dic["response"]["body"]["items"]["item"][j]["dutyName"])

    except :
        try:
            # item의 개수가 1개인 경우
            print("\t"+dic["response"]["body"]["items"]["item"]["dutyName"])
        except : 
            # item의 개수가 0개인 경우
            print("\t NaN")

 

 

 

위의 코드는 주석을 통해 간단하게 설명해놓았다. 

내가 목표했던 시도군 병원 이름이 잘 출력된 것을 확인할 수 있다. 

 


🧐 다음 목표

다음에는 해당 병원들의 위치와 의료종합상황판을 folium으로 나타내보려고 한다.

folium은 예전에 딱 한번만 써봐서 기억이 잘 나지않지만 ...

열심히 준비하고 정리해보려고 한다 !