2016년 1월 5일 화요일

기상청 날씨 API 개선방안

 기상청 날씨 서비스를 위한 성능 개선 방안을 다룬다.


먼저 기본적인 사용 방법이다.


1. “위/경도” 또는 “지명 이름”를 “격좌 좌표”로 변한
2. “격좌 좌표”를 기상청 API에 조회 (날씨)

조회가 발생할 때마다 기상청 API를 호출하는 것은 비효율적이다.


다음은 성능 개선 방안이다.


1. “지역 이름”에 해당하는 “날씨 정보”를 일괄 수집한다. (총 3772, 시단위 84)
=> 수집된 데이터는 “지역 이름”, “위/경도”, “격자 좌표”,  “날씨 정보” 속성을 가진다.
2. 위/경도를 역지오코딩으로 “지역 이름”을 추출한다.
3. “지역 이름”에 해당되는 “날씨 정보”를 반환한다.



만들어 놓은 것만 쓰다보니 그림과 같은 1차 발상을 한다.
역지오코딩을 통해 "지역 이름"을 추출하는 것이 API 서비스를 통해서 다음/네이버에서 제공된다. 속도가 느린 것이 당연한 API 서비스다.!!

더 낳은 방안을 찾다.


날씨에 중요한 건 “지역 이름”이 아니라 관측 장소와 거리이다.
“위/경도” 좌표 기준으로 최단 거리에 해당하는 지역의 "날씨 정보"를 반환하자.

최단 거리는 min() 구하는 로직이라 시간 복잡도 O(n)으로 충분하다.

사무실에 가만히 공상하는 것이 낯선 환경에서는 생각은 짧고 손은 분주하다.


검증을 위해 구현한 예제 코드이다.

import pandas as pd
import sqlite3
conn = sqlite3.connect('kma.db')
df = pd.read_sql('select * from loc_map_book',con=conn)

df = df [ df['lev3'] == '-' ]
df['city'] = df['lev2'].apply(lambda i: i[-1] == '시' or i[-1] == '-')
TPS = df[ df['city'] ].to_dict(orient = 'records')

df.head(3)
OUT>>

lev1
lev2
lev3
nx
ny
lon
lat
city
0
서울특별시
-
-
60
127
126.980008
37.563569
TRUE
1
서울특별시
종로구
-
60
127
126.981642
37.570378
FALSE
19
서울특별시
중구
-
60
127
126.999642
37.561003
FALSE

def closest_pair(lon,lat):
    _min_dist = pow(TPS[0]['lon'] - lon, 2) + pow(TPS[0]['lat'] - lat, 2)
    
    for tp in TPS[1:]:
        _cur_dist = pow( tp['lon'] - lon,2 ) + pow( tp['lat'] - lat, 2 )
        
        if _cur_dist < _min_dist:
            _min_dist = _cur_dist
            _out_pair = tp
    
    return _out_pair

closest_pair(132,37) # 울릉도
OUT>>
{'city': True,
 'lat': 37.44708611111111,
 'lev1': '강원도',
 'lev2': '삼척시',
 'lev3': '-',
 'lon': 129.16748888888887,
 'nx': 98,
 'ny': 125}

울릉도의 경우 가장 가까운 "강원도 삼척시"가 나온다.



0 개의 댓글:

댓글 쓰기