관리 메뉴

솜씨좋은장씨

[Python] 공공api를 활용하여 내 주변 공적 마스크 판매처와 마스크 재고를 지도에 시각화해보자! 본문

Programming/Python

[Python] 공공api를 활용하여 내 주변 공적 마스크 판매처와 마스크 재고를 지도에 시각화해보자!

솜씨좋은장씨 2020. 3. 14. 23:28
728x90
반응형

최근 코로나바이러스로 인하여 마스크 구입량이 수요가 급격히 늘어남에 따라 일반 온라인 / 오프라인 판매처에서 구매가 어려워져

급증하는 수요를 감당하기 위하여 정부에서는 마스크 5부제를 시행하고 있습니다.

 

이에 카카오맵 / 네이버 지도 같은 서비스에서 약국을 검색하면

마스크 공적판매처인지 아닌지에 대한 정보와 남은 마스크 수량등을 알려주는 기능이 추가되고 있기도 합니다.

 

오늘은 정부에서 제공하는 공적마스크판매처 API와

지난 국토 데이터 분석 경진대회에서 사용하였던 folium 라이브러리를 통해

카카오맵이나 네이버 지도에서 서비스를 하고 있는 것처럼 직접 지도에 시각화 해보기로 했습니다.

 

2020년 9월 30일 업데이트

공적마스크 판매 중단으로 인하여 7월 8일 부로 API 지원이 종료 되었습니다.

 

공공데이터 포털

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

www.data.go.kr

 

모든 공적 마스크 판매처 지도에 시각화하기

판매처 데이터 받아와서 csv형태로 저장하기

먼저 전체 판매처에 대한 지도 시각화를 해보았습니다.

 

공공데이터포털

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

www.data.go.kr

현재 공적마스크 판매처에 대한 데이터는 공공데이터 포털에서 API형식으로 제공하고 있습니다.

 

항상 공공데이터 포털의 API를 사용하려면 키를 발급받아 사용했어야했는데 이번 API는 별도의 등록이나 키발급이 필요없었습니다.

 

요청 url은 다음과 같습니다.

"https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/stores/json?page=1"

먼저 데이터 요청시 제대로 데이터가 받아와지는지 확인해보았습니다.

import requests
import json
from tqdm import tqdm
import pandas as pd

url = "https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/stores/json?page=1"

req = requests.get(url)

json = req.json()
json

요청에는 requests 라이브러리를 활용하였고

받아온 데이터의 형태가 json 형태이므로 이를 dictionary형태로 바꾸어 key값을 통해 원하는 값을 추출하기위해서

json 라이브러리를 사용했습니다.

 

우리는 전체 데이터를 한번에 받고 싶으므로 totalPages라는 키값에 있는 전체 페이지 수 값을 가져와 활용하였습니다.

이를 활용하여 전체 데이터를 불러오는 함수를 만들었습니다.

def getMaskStoreInfo():
    url = "https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/stores/json?page=1"
    
    req = requests.get(url)
    
    total_page = req.json()['totalPages']
    
    addrs = []
    codes = []
    latitudes = []
    longitudes = []
    names = []
    types = []
    
    for page_num in tqdm(range(1, total_page+1)):
        url = "https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/stores/json?page=" + str(page_num)
        
        req = requests.get(url)
        
        json_data = req.json()
        
        store_infos = json_data['storeInfos']
        
        for info in store_infos:
            addrs.append(info['addr'])
            codes.append(info['code'])
            latitudes.append(info['lat'])
            longitudes.append(info['lng'])
            names.append(info['name'])
            types.append(info['type'])
            
    
    mask_store_info_df = pd.DataFrame({"addr":addrs, "code":codes, "latitude":latitudes, "longitude":longitudes, "name":names, "type":types})
    
    return mask_store_info_df

1페이지부터 54페이지까지 모든 데이터를 가져오는데

주소, 코드, 위도, 경도, 약국 또는 마트명, 타입에 대한 정보를 가져와서 list에 저장한 후

마지막에 DataFrame형식으로 return하도록 하였습니다.

진행상황을 눈으로 보고 싶어 tqdm라이브러리를 통하여 실시간 진행현황을 출력하도록 하였습니다.

my_info_df = getMaskStoreInfo()

한번 제대로 동작하는지 실행해보니.... 주소가 없는 데이터가 있어 오류가 나는 것이었습니다.

url = "https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/stores/json?page=40"
req = requests.get(url)
json = req.json()

addrs = []
codes = []
latitudes = []
longitudes = []
names = []
types = []

store_infos = json['storeInfos']
        
for i in range(len(store_infos)):
    try:
        addrs.append(store_infos[i]['addr'])
    except:
        print("add", i)
    try:
        codes.append(store_infos[i]['code'])
    except:
        print("code", i)
    try:
        latitudes.append(store_infos[i]['lat'])
    except:
        print("lat", i)
    try:
        longitudes.append(store_infos[i]['lng'])
    except:
        print("lng", i)
    try:
        names.append(store_infos[i]['name'])
    except:
        print("name", i)
    try:
        types.append(store_infos[i]['type'])
    except:
        print("type", i)

tqdm이 출력하던 진행상황에서 오류가나 멈췄을때의 index를 바탕으로 어느 페이지에 결측치가 존재하는지 알 수 있었고

이를 바탕으로 해당페이지에서 어떤 데이터가 문제가 있는지 찾아보았습니다.

40페이지의 456번째의 데이터가 주소, 코드, 이름, 타입이 누락되어있는 것을 알 수 있었습니다.

또 53페이지의 113번째 데이터도 주소가 누락되어있는 것을 알 수 있었습니다.

 

이에 전체 정보를 가져오는 가져오는 함수를 조금 수정하여 이상없이 데이터를 받아올 수 있었습니다.

def getMaskStoreInfo():
    url = "https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/stores/json?page=1"
    
    req = requests.get(url)
    
    total_page = req.json()['totalPages']
    
    addrs = []
    codes = []
    latitudes = []
    longitudes = []
    names = []
    types = []
    
    for page_num in tqdm(range(1, total_page+1)):
        url = "https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/stores/json?page=" + str(page_num)
        
        req = requests.get(url)
        
        json_data = req.json()
        
        store_infos = json_data['storeInfos']
        
        for i in range(len(store_infos)):
            if (page_num != 40 and i != 456) and (page_num != 53 and i != 113):
                addrs.append(store_infos[i]['addr'])
                codes.append(store_infos[i]['code'])
                latitudes.append(store_infos[i]['lat'])
                longitudes.append(store_infos[i]['lng'])
                names.append(store_infos[i]['name'])
                types.append(store_infos[i]['type'])
            
    
    mask_store_info_df = pd.DataFrame({"addr":addrs, "code":codes, "latitude":latitudes, "longitude":longitudes, "name":names, "type":types})
    
    return mask_store_info_df
my_info_df = getMaskStoreInfo()

:

두개 데이터에 대한 예외처리 후 이상없이 잘 받아오는 것을 볼 수 있었습니다.

 

이 데이터는 추후 별도의 api 호출없이 재사용이 가능하도록 csv 파일 형태로 저장해주었습니다.

my_info_df.to_csv("mask_store_info.csv", index=False)

 

Folium라이브러리를 통하여 지도에 시각화하기

이제 folium을 활용하여 지도에 그려보겠습니다.

 

먼저 다음 명령어를 통하여 folium을 설치해줍니다.

터미널 / 명령프롬프트의 경우

pip3 install folium

주피터 노트북의 경우

!pip3 install folium

import folium
from folium.plugins import MarkerCluster, MiniMap

설치를 완료하였다면 필요한 라이브러리를 import 시켜줍니다.

data_for_draw = my_info_df.loc[:, ['name', 'latitude', 'longitude']]
data_for_draw

그리고 우리가 지도에 시각화할때 필요한 데이터만 loc 메소드를 통해 가져옵니다.

:

folium으로 시각화 하기전에 문제가되는 결측치를 제거합니다.

data_for_draw_except_nan = data_for_draw.dropna()
data_for_draw_except_nan

:

약 400개 가량의 데이터가 제거된 것을 알 수 있었습니다.

 

이 데이터를 가지고 지도에 시각화를 해보았습니다.

map_hs = folium.Map((37.1995439, 126.8311358), zoom_start = 13)
mc = MarkerCluster()

names = list(data_for_draw_except_nan['name'])
latitudes = list(data_for_draw_except_nan['latitude'])
longitudes = list(data_for_draw_except_nan['longitude'])

for i in tqdm(range(len(names))):
    mc.add_child(folium.Marker(location = [latitudes[i], longitudes[i]], popup=names[i]))
    map_hs.add_child(mc)

map_hs.save("./mask_store.html")

데이터의 크기가 크면 주피터 노트북에서 제대로 출력을 하지 못하므로

시각화한 데이터를 html형식으로 저장하여 확인해보았습니다.

이상없이 잘 시각화가 된 것을 확인할 수 있었습니다.

제가 살고있는 노량진동을 기준으로 확대해보면 다음과 같이 마커 형태로 시각화가 되어있는 것을 확인할 수 있고

각각의 마커를 클릭하면 약국의 이름이 보이도록 하였습니다.

 

판매처 데이터에 마스크 재고 데이터 추가하기

여기까지하고 공공데이터 포털에서 참고문서로 알려준 링크로 들어가보았습니다.

참고문서 링크 바로가기

 

api중에 /sales/json 으로 마스크 재고 데이터도 제공되고 있는 것을 알 수 있었습니다.

 

Try it out을 클릭하여 실행해보니

다음과 같은 데이터를 얻을 수 있었습니다.

데이터는 다음과 같이 구성되어있었습니다.

 

Sales

  • code : 식별코드
  • created_at : 데이터 생성 일자
  • remain_stat : 재고상태
  • stock_at : 입고시간

여기서 아까 판매처 정보를 가져왔을때 있었던 code 데이터를 활용해서

Sales의 데이터를 판매처 정보 데이터에 추가할 수 있겠다고 생각하였습니다.

 

먼저 이전에 받아온 판매처 데이터의 code값을 통하여 값을 적용할 수 있도록

API에서 데이터를 호출하여

code를 키값으로 하는 새로운 dictionary를 만들어주었습니다.

def getMaskStoreSalesInfo():
    url = "https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/sales/json?page=1"
    
    req = requests.get(url)
    
    total_page = req.json()['totalPages']
    
    
    sales_dict = {}
    
    for page_num in tqdm(range(1, total_page+1)):
        url = "https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/sales/json?page=" + str(page_num)
        
        req = requests.get(url)
        
        json_data = req.json()
        
        sales_infos = json_data['sales']
        
        for i in range(len(sales_infos)):
            code = sales_infos[i]['code']
            created_at = sales_infos[i]['created_at']
            remain_stat = sales_infos[i]['remain_stat']
            stock_at = sales_infos[i]['stock_at']

            sales_dict[code] = {"created_at":created_at, "remain_stat":remain_stat, "stock_at":stock_at}

    return sales_dict

이 함수를 통해서 dictionary를 생성하려고하니

sales_dict = getMaskStoreSalesInfo()

여기서도 결측치로 인하여 오류가 나는 것을 볼 수 있었습니다.

def getMaskStoreSalesInfo():
    url = "https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/sales/json?page=1"
    
    req = requests.get(url)
    
    total_page = req.json()['totalPages']
    
    
    sales_dict = {}
    
    for page_num in tqdm(range(1, total_page+1)):
        url = "https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/sales/json?page=" + str(page_num)
        
        req = requests.get(url)
        
        json_data = req.json()
        
        sales_infos = json_data['sales']
        
        for i in range(len(sales_infos)):
            code = sales_infos[i]['code']
            try:
                created_at = sales_infos[i]['created_at']
            except:
                created_at = "no_data"
            try:
                remain_stat = sales_infos[i]['remain_stat']
            except:
                remain_stat = "no_data"
            try:
                stock_at = sales_infos[i]['stock_at']
            except:
                stock_at = "no_data"
                

            sales_dict[code] = {"created_at":created_at, "remain_stat":remain_stat, "stock_at":stock_at}

    return sales_dict

이를 해결하기위해서 아까 조건문을 달았던 것과 다르게 try / except를 사용하여 데이터가 없는경우 no_data를 입력하도록 하였습니다.

sales_dict = getMaskStoreSalesInfo()

이상없이 데이터를 받아오는 것을 볼 수 있습니다.

 

이제 판매처 데이터에 code를 키값으로 재고 데이터를 추가해보도록 하겠습니다.

 

아까 csv 파일로 저장해 두었던 파일을 pandas의 read_csv를 활용하여 load해줍니다.

my_info_df = pd.read_csv("mask_store_info.csv")
def mergeSalesInfobyStoreCode(sales_dict, my_info_df):
    store_codes = list(my_info_df['code'])
    
    created_ats = []
    remain_stats = []
    stock_ats = []

    for i in tqdm(range(len(store_codes))):
        try:
            store_sales_info = sales_dict[str(store_codes[i])]
            
            created_ats.append(store_sales_info['created_at'])
            remain_stats.append(store_sales_info['remain_stat'])
            stock_ats.append(store_sales_info['stock_at'])
        except:
            created_ats.append("no_data")
            remain_stats.append("no_data")
            stock_ats.append("no_data")
            
    my_info_df['created_at'] = created_ats
    my_info_df['remain_stat'] = remain_stats
    my_info_df['stock_at'] = stock_ats
    
    return my_info_df

각각의 판매처 code를 통해 데이터를 추가하도록 합니다.

my_store_and_sales_info_df = mergeSalesInfobyStoreCode(sales_dict, my_info_df)

:

이상없이 잘 합쳐진 것을 볼 수 있습니다.

 

이제!

 

이 재고 데이터도 지도에 함께 시각화 해보겠습니다.

 

그 전에 api 상세 보기 문서에서 시각화할때 지켜달라고 한 조건을 살펴보면 

재고상태에 따른 시각화 색상

  • 'plenty' (100개 이상) : 녹색
  • 'some' (30개 이상) : 노랑색
  • 'few' (2개이상 30개 미만) : 빨강색
  • 'empty' (1개이하) : 회색
  • 'break' (판매중지) : 없음
  • 'no_data (데이터가 존재하지 않음) : 보라색

인 것을 볼 수 있습니다.

'no_data' 는 원래 명세서에 존재하지 않지만 결측치를 표현하기위해서 임의로 선택한 색상입니다.

 

 

이를 마커 색상에 적용하여 한번 시각화 해보도록 하겠습니다.

 

 

data_for_draw2 = my_store_and_sales_info_df.loc[:, ['name', 'latitude', 'longitude', 'remain_stat']]
data_for_draw2

먼저 필요한 데이터만 추출하여줍니다.

 

:

data_for_draw2_nan = data_for_draw2.dropna()
data_for_draw2_nan

:

dropna( )로 결측치를 제거해 주었습니다.

data_for_draw_except_nan2 = data_for_draw_except_nan2[data_for_draw_except_nan2['remain_stat'] != 'break']
data_for_draw_except_nan2

판매가 중지된 약국은 시각화해도 의미가 없으므로 제거해줍니다.

:

 

Folium으로 시각화하기

먼저 명세서의 조건대로 마커의 색상이 지정되도록 색상 dictionary를 하나 만들어줍니다.

여기서 노란색을 사용하면 warning이 나와 orange로 대체해보았습니다.

color_dic = {
	'plenty':'green', 
    	'some':'orange', 
    	'few':'red', 
    	'empty':'gray', 
    	'no_data':'purple'
    }
remain_stat_kor = {
	'plenty':'100개 이상', 
    	'some':'30개 이상', 
        "few":'2개이상 30개 미만', 
        "empty":"재고 없음", 
        "no_data":"정보 없음"
}

마커에 표시할때 재고 정보가 한국어로 보이도록 하기위한 dictionary도 하나 만들어줍니다.

map_hs2 = folium.Map((37.1995439, 126.8311358), zoom_start = 13)
mc2 = MarkerCluster()

names = list(data_for_draw_except_nan2['name'])
latitudes = list(data_for_draw_except_nan2['latitude'])
longitudes = list(data_for_draw_except_nan2['longitude'])
remain_stats = list(data_for_draw_except_nan2['remain_stat'])

for i in tqdm(range(len(names))):
    mc2.add_child(folium.Marker(location = [latitudes[i], longitudes[i]], icon=folium.Icon(color=color_dic[remain_stats[i]]), popup=names[i] + ' ' + remain_stat_kor[remain_stats[i]]))
    map_hs2.add_child(mc2)

folium으로 마커를 만들면서 remain_stat값을 키 값으로 활용하여 각각의 조건에 해당하는 색상을 적용하도록 합니다.

map_hs2.save("./mask_store3.html")

저장하여 확인해보겠습니다.

제가 살고 있는 곳 주변의 판매처 정보를 확인해보니 신안약국이라는 곳에 2개~30개 미만의 마스크가 남아있는 것을 확인할 수 있었습니다.

토요일이라 모두가 구매할수있는 날이었지만 너무 늦은 시간이라 이미 약국이 문을 닫아 구매를 할 수는 없었습니다.

 

이렇게 시각화를 해보았습니다.

 

그런데 현재는 약 25,000개의 데이터를 모두 시각화 하기때문에

저장한 html 파일을 오픈하여 보려고하면 로딩하는데 시간이 오래걸립니다.

 

이는 api에서 주소를 통해 주변 판매처를 검색하는 기능을 통해 시각화 하는 데이터의 수를 줄여 해결할 수 있습니다.

 

내 주변 판매처만 시각화 하기

제가 살고있는 동작구 기준으로 실행해보았습니다.

이 기능을 나중에 알았는데 재고 정보까지 같이 제공되고있어 훨씬 편리했습니다.

 

def getNearMaskStoreInfo(address):
    url = "https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/storesByAddr/json?address=" + requests.utils.unquote(address)
    
    req = requests.get(url)
    
    json_data = req.json()
    store_data = json_data['stores']
    
    addrs = []
    codes = []
    latitudes = []
    longitudes = []
    names = []
    types = []
    created_ats = []
    remain_stats = []
    stock_ats = []
    
    for i in tqdm(range(len(store_data))):
        addrs.append(store_data[i]['addr'])
        codes.append(store_data[i]['code'])
        latitudes.append(store_data[i]['lat'])
        longitudes.append(store_data[i]['lng'])
        names.append(store_data[i]['name'])
        types.append(store_data[i]['type'])
        try:
            created_ats.append(store_data[i]['created_at'])
        except:
            created_ats.append("no_data")
        try:
            remain_stats.append(store_data[i]['remain_stat'])
        except:
            remain_stats.append("no_data")
        try:
            stock_ats.append(store_data[i]['stock_at'])
        except:
            stock_ats.append("no_data")

            
    print(len(addrs), len(codes), len(latitudes), len(longitudes), len(names), len(types), len(created_ats), len(remain_stats), len(stock_ats))

    
    mask_store_info_df = pd.DataFrame({"addr":addrs, "code":codes, "latitude":latitudes, "longitude":longitudes, "name":names, "type":types, "created_at":created_ats, "remain_stat":remain_stats, "stock_at":stock_ats})
    
    return mask_store_info_df

제가 거주하고있는 동작구의 판매처만 데이터를 요청해보았습니다.

mask_store_info = getNearMaskStoreInfo("서울특별시 동작구")
mask_store_info

:

총 190개의 데이터로 원하는 지역의 데이터만 받아와 전체의 데이터를 불러왔을때보다 훨씬 적은 양임을 알 수 있습니다.

data_for_draw3 = mask_store_info.loc[:, ['name', 'latitude', 'longitude', 'remain_stat']]
data_for_draw3

:

data_for_draw_except_nan3 = data_for_draw3.dropna()
data_for_draw_except_nan3 = data_for_draw_except_nan3[data_for_draw_except_nan3['remain_stat'] != 'break']
data_for_draw_except_nan3

 

결측치를 제거하고 판매가 중단된 판매처는 제거합니다.

:

190개의 데이터에서 164개의 데이터만 남은 것을 볼 수 있습니다.

이를 활용하여 folium으로 시각화해보았습니다.

map_hs3 = folium.Map((37.513516, 126.940233), zoom_start = 14)
mc3 = MarkerCluster()

names = list(data_for_draw_except_nan3['name'])
latitudes = list(data_for_draw_except_nan3['latitude'])
longitudes = list(data_for_draw_except_nan3['longitude'])
remain_stats = list(data_for_draw_except_nan3['remain_stat'])

for i in tqdm(range(len(names))):
    mc3.add_child(folium.Marker(location = [latitudes[i], longitudes[i]], icon=folium.Icon(color=color_dic[remain_stats[i]]), popup=names[i] + ' ' + remain_stat_kor[remain_stats[i]]))
    map_hs3.add_child(mc3)

map_hs3.save("./mask_store4.html")

데이터의 양이 줄어 이전보다 더 빠르게 로딩되어 더 보기 편했습니다.

 

좌표 기준 m 미터 이내의 판매처만 그려보기

마지막으로 좌표를 기준으로 반경 m미터 이내의 판매처만 가져와보았습니다.

노량진역 3번출구 근처의 좌표를 기준으로 반경 1,000미터의 판매처만 가져와 보았습니다.

def getNearMaskStoreInfoByGeo(lat, lng, dist):
    url = "https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/storesByGeo/json?lat=" + str(lat) + "&lng=" + str(lng) + "&m=" + str(dist)
    
    req = requests.get(url)
    
    json_data = req.json()
    store_data = json_data['stores']
    
    addrs = []
    codes = []
    latitudes = []
    longitudes = []
    names = []
    types = []
    created_ats = []
    remain_stats = []
    stock_ats = []
    
    for i in tqdm(range(len(store_data))):
        addrs.append(store_data[i]['addr'])
        codes.append(store_data[i]['code'])
        latitudes.append(store_data[i]['lat'])
        longitudes.append(store_data[i]['lng'])
        names.append(store_data[i]['name'])
        types.append(store_data[i]['type'])
        try:
            created_ats.append(store_data[i]['created_at'])
        except:
            created_ats.append("no_data")
        try:
            remain_stats.append(store_data[i]['remain_stat'])
        except:
            remain_stats.append("no_data")
        try:
            stock_ats.append(store_data[i]['stock_at'])
        except:
            stock_ats.append("no_data")
    
    mask_store_info_df = pd.DataFrame({"addr":addrs, "code":codes, "latitude":latitudes, "longitude":longitudes, "name":names, "type":types, "created_at":created_ats, "remain_stat":remain_stats, "stock_at":stock_ats})
    
    return mask_store_info_df
lat = 37.513489
lng = 126.941986
m = 1000
mask_store_info_by_geo = getNearMaskStoreInfoByGeo(lat, lng, m)
mask_store_info_by_geo

:

data_for_draw4 = mask_store_info_by_geo.loc[:, ['name', 'latitude', 'longitude', 'remain_stat']]
data_for_draw4

:

data_for_draw_except_nan4 = data_for_draw4.dropna()
data_for_draw_except_nan4 = data_for_draw_except_nan4[data_for_draw_except_nan4['remain_stat'] != 'break']
new_index = []
for i in range(len(data_for_draw_except_nan4['name'])):
    new_index.append(i)
data_for_draw_except_nan4.index = new_index
data_for_draw_except_nan4

:

map_hs4 = folium.Map((lat, lng), zoom_start = 14)
mc4 = MarkerCluster()

names = list(data_for_draw_except_nan4['name'])
latitudes = list(data_for_draw_except_nan4['latitude'])
longitudes = list(data_for_draw_except_nan4['longitude'])
remain_stats = list(data_for_draw_except_nan4['remain_stat'])

for i in tqdm(range(len(names))):
    mc4.add_child(folium.Marker(location = [latitudes[i], longitudes[i]], icon=folium.Icon(color=color_dic[remain_stats[i]]), popup=names[i] + ' ' + remain_stat_kor[remain_stats[i]]))
    map_hs4.add_child(mc4)

map_hs4.save("./mask_store4.html")

 

오늘은 여기까지! 다음에 시간이 있다면 이 api를 활용해서 나만의 마스크 재고알림 텔레그램 챗봇을 만들어보고자 합니다.

 

읽어주셔서 감사합니다!

 

SOMJANG/Korea_Public_Mask_Store_Visualization

마스크 공적판매처 위치 지도 시각화. Contribute to SOMJANG/Korea_Public_Mask_Store_Visualization development by creating an account on GitHub.

github.com

 

Comments