📚공공데이터 활용하기
공공데이터를 사용해서 할 수 있는 것은 정말 많다.
공공데이터 기반 웹/앱 서비스도 가능하다.
그래서 이번 포스팅은 공공데이터를 가져와서,
내가 원하는 정보를 출력하는 것 까지를 목표로 한다.
📖 공공데이터 가입/신청
공공데이터 포털에 들어가서 회원가입을 한다.
그리고 원하는 데이터를 검색하고 찾는다.
https://www.data.go.kr/data/15000563/openapi.do
지금 이 포스팅에서는 "국립중앙의료원_전국 응급의료기관 정보 조회 서비스" 데이터를 사용 할 것이다 .
데이터를 사용 하려면 활용 신청을 해야하는데, 해당 데이터에 들어가 활용신청을 하면 바로 승인이 된다.
📖 신청한 공공데이터 살펴보기
승인 신청이 완료되면, 활용신청 현황에 이렇게 표시가 된다.
"오픈 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를 이렇게 데이터프레임으로도 쉽게 나타낼 수 있다. )
📖 전국 시도군 병원 이름 출력하기
방금 위에서 출력한 병원은 "서울특별시"의 "강남구" 병원 밖에 없다.
포스팅의 목표는 전국 시도군 병원 이름을 모두 출력하는 것이다.
내가 원하는대로 출력을 하려면 전국 시도의 정보가 있어야 한다.
우선, 위의 법정동 기둥 시도 정보 파일들을 다운로드 하자.
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은 예전에 딱 한번만 써봐서 기억이 잘 나지않지만 ...
열심히 준비하고 정리해보려고 한다 !
'Open API' 카테고리의 다른 글
[Python] 병원명으로 위도와 경도 나타내기 (Open API 네이버 검색) (1) | 2024.04.02 |
---|---|
[Python] 카카오 api로 나에게 메시지 보내기 (+ 메시지 템플릿) (1) | 2023.10.18 |