위도 경도 값을 이용하여 거리를 구하고 그래프를 그려보자.¶
안녕하세요 :) 좌표값을 haversine이라는 공식을 이용하여 지구 반경등을 사용하여 거리를 구해보고, 여기에 해당 좌표들의 고도 값을 이용하여 그래프를 그려보도록 하겠습니다.
In [94]:
import matplotlib.pyplot as plt
%matplotlib inline
import platform
from matplotlib import font_manager, rc
plt.rcParams['axes.unicode_minus']=False
if platform.system() == 'Darwin':
rc('font', family='AppleGothic')
elif platform.system() == 'Windows':
path = "c:/Windows/Fonts/malgun.ttf"
font_name = font_manager.FontProperties(fname = path).get_name()
rc('font', family = font_name)
else:
print('Unkown system... sorry~~~~')
그래프를 그릴 때 한글이 깨지지 않도록 사용하는 코드입니다. 자주 사용하게 되니 알아두세요.
In [95]:
import numbers
import math
from geopy.geocoders import Nominatim
geolocator = Nominatim()
class GeoUtil:
"""
Geographical Utils
"""
@staticmethod
def degree2radius(degree):
return degree * (math.pi/180)
@staticmethod
def get_harversion_distance(x1, y1, x2, y2, round_decimal_digits=5):
"""
경위도 (x1,y1)과 (x2,y2) 점의 거리를 반환
Harversion Formula 이용하여 2개의 경위도간 거래를 구함(단위:Km)
"""
if x1 is None or y1 is None or x2 is None or y2 is None:
return None
assert isinstance(x1, numbers.Number) and -180 <= x1 and x1 <= 180
assert isinstance(y1, numbers.Number) and -90 <= y1 and y1 <= 90
assert isinstance(x2, numbers.Number) and -180 <= x2 and x2 <= 180
assert isinstance(y2, numbers.Number) and -90 <= y2 and y2 <= 90
R = 6371 # 지구의 반경(단위: km)
dLon = GeoUtil.degree2radius(x2-x1)
dLat = GeoUtil.degree2radius(y2-y1)
a = math.sin(dLat/2) * math.sin(dLat/2) \
+ (math.cos(GeoUtil.degree2radius(y1)) \
*math.cos(GeoUtil.degree2radius(y2)) \
*math.sin(dLon/2) * math.sin(dLon/2))
b = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
return round(R * b, round_decimal_digits)
haversine 공식은 좌표계 변환과 삼각함수를 이용하여 거리를 구하는 공식입니다. 소스는 제가 원하는 형태로 짜집기 해온 코드입니다. 좌표를 이용해서 어떤 프로젝트를 하거나 할때 유용하게 쓰일 수 있습니다.
In [96]:
Route_LatLng = [[37.5764873, 126.9854266], [37.57684, 126.98618], [37.577516, 126.9858367], [37.5778665, 126.9856691], [37.5781121, 126.9855516], [37.5782186, 126.985506], [37.5790391, 126.9851173], [37.5792618, 126.9849995], [37.5796173, 126.984966], [37.5800671, 126.984992], [37.5801629, 126.9849962], [37.5805961, 126.9850118], [37.5809155, 126.9850293], [37.5812312, 126.9850139], [37.5814686, 126.9850111], [37.5818577, 126.9843257], [37.5821692, 126.9836089], [37.5823256, 126.983551], [37.5824217, 126.9836735], [37.5829857, 126.9834767], [37.5834721, 126.98306], [37.5834848, 126.9829258], [37.5839766, 126.9829677], [37.5839889, 126.9826768], [37.5839907, 126.9825698], [37.5840336, 126.9826416], [37.5843184, 126.9822764], [37.5844481, 126.9820227], [37.5845466, 126.9820455], [37.5846562, 126.9820518], [37.5848361, 126.9820462], [37.5850625, 126.9820218], [37.5851596, 126.9820188], [37.5852425, 126.9820106], [37.5857697, 126.9818111], [37.5862357, 126.9816655]]
ele = [45.155, 43.766, 42.196, 41.018, 40.381, 40.578, 43.174, 43.691, 44.423, 45.329, 45.725, 48.678, 50.726, 52.532, 53.93, 57.716, 63.152, 64.438, 64.618, 68.689, 69.221, 68.371, 68.622, 65.147, 63.865, 64.564, 59.612, 56.666, 56.637, 56.475, 56.209, 56.313, 56.467, 56.648, 58.841, 60.125]
print(len(Route_LatLng),len(ele))
예시를 보여 드리기 위해 임의의 길에 대한 좌표값들(출발지에서 도착지까지의 좌표값들)과 그 해당 좌표에서의 고도값들을 설정해주었습니다.
In [97]:
Lat=[]
for i in range(len(Route_LatLng)):
lat = Route_LatLng[i][0]
a = [lat]
Lat.append(a)
len(Lat)
Out[97]:
In [98]:
Lng=[]
for i in range(len(Route_LatLng)):
lng = Route_LatLng[i][1]
a = [lat]
Lng.append(a)
len(Lng)
Out[98]:
In [115]:
def What_Km(route):
add=[]
for i in range(len(route)-1):
lng1 = route[i][0]
lat1 = route[i][1]
lng2 = route[i+1][0]
lat2 = route[i+1][1]
result =GeoUtil.get_harversion_distance(lat1,lng1,lat2,lng2)
add.append(result)
return '총 거리는 ' + str(round(sum(add),2)) + 'KM 입니다.'
In [100]:
Route_LatLng[0][1]
Out[100]:
In [101]:
def Not_sum_What_Km(route):
add=[0] #0을 넣어줘서 출발점 생성.
for i in range(len(route)-1):
lng1 = route[i][0]
lat1 = route[i][1]
lng2 = route[i+1][0]
lat2 = route[i+1][1]
result =GeoUtil.get_harversion_distance(lat1,lng1,lat2,lng2)
c=add[i]+result
add.append(c)
return add
그래프를 그리는데 필요한 함수들을 만들어줍니다.
In [116]:
def godograph():
# from Numeric import asarray
%matplotlib inline
P1 = Route_LatLng[0] #start
P2 = Route_LatLng[len(Route_LatLng)-1] #end
lat0=P1[0]
lon0=P1[1]
lat_list=Lat
lon_list=Lng
leng=Not_sum_What_Km(Route_LatLng)
mean_elev=round((sum(ele)/len(ele)),3)
min_elev=min(ele)
max_elev=max(ele)
distance=leng[-1]
plt.figure(figsize=(14,5))
plt.xlim(0, leng[len(leng)-1])
plt.ylim(30, max(ele)+5)
plt.plot(leng,ele)
plt.plot([0,distance],[min_elev,min_elev],'--g',label='최저: '+str(min_elev)+' m')
plt.plot([0,distance],[max_elev,max_elev],'--r',label='최고: '+str(max_elev)+' m')
plt.plot([0,distance],[mean_elev,mean_elev],'--y',label='평균: '+str(mean_elev)+' m')
plt.fill_between(leng,ele,30,alpha=0.3)
plt.annotate('출발',size='18',xy=(leng[0],ele[0]),xytext=(leng[0],ele[0]+5),arrowprops={'color':'black'})
plt.text(leng[-1],ele[-1],"도착",size='18',color='black')
plt.xlabel("Distance(km)",size='16',color='darkblue')
plt.ylabel("Elevation(m)",size='16',color='darkblue')
plt.grid()
plt.legend(fancybox=True, framealpha=1, shadow=True, borderpad=0.6,loc=2,fontsize='10')
print(What_Km(Route_LatLng))
return plt.show()
In [118]:
godograph()
이렇게 결과물이 나왔습니다. 보기좋게 좀 꾸며봤는데요. 응용하여 잘 쓰일 수 있는 코드들이라고 생각합니다:)
'데이터분석 및 프로젝트' 카테고리의 다른 글
수열을 통해 마코프 체인의 단서를 얻어보자 :) (0) | 2020.01.15 |
---|---|
머신러닝을 이용해 데이터분석에 필요한 기초지식을 습득해보자 :) (0) | 2020.01.15 |
LZW 알고리즘과 허프만 부호화 방법을 서로 비교하여 분석해보자. (0) | 2020.01.08 |
기사를 크롤링하여 워드클라우드를 만들어보자. (0) | 2020.01.08 |
크롤링과 코사인 유사도를 이용하여 영화추천 서비스를 만들어보자 :) (2) | 2020.01.07 |