使用简单的 python 脚本从经纬度坐标获取高程
Obtain elevation from latitude longitude coordinates with a simple python script
我有一个 python 脚本,我从这个 question 中获得了该脚本,该脚本将从 USGS 高程点查询服务中提取。但是,它一直超时,并在看似随机的时间后和我的查询完成之前将我踢出局。我需要另一种方法来在给定经纬度坐标的情况下提取高程数据。
这是我当前的查询:
# ========= pull elev from usgs server ======
# USGS POINT QUERY SERVICE ==================
url = r'https://nationalmap.gov/epqs/pqs.php?'
# ===========================================
# coordinates with known elevation
lat = [48.633, 48.733, 45.1947, 45.1962]
lon = [-93.9667, -94.6167, -93.3257, -93.2755]
# create df
df = pd.DataFrame({
'lat': lat,
'lon': lon
})
def elevation_function(df, lat_column, long_column):
elevations = []
counter = 0
start = time.time()
for lat, lon in zip(df[lat_column], df[long_column]):
# define rest query params
params = {
'output': 'json',
'x': lon,
'y': lat,
'units': 'Meters'
}
# format query string and return query value
result = requests.get((url + urllib.parse.urlencode(params)))
elevations.append(result.json()['USGS_Elevation_Point_Query_Service']['Elevation_Query']['Elevation'])
counter += 1
print('Proportion of job complete: {}'.format(round(counter/df.shape[0],3)))
end = time.time()
print(str(round(end - start)) + " seconds into job\n")
df['elev'] = elevations
return elevations
start = time.time()
count = 0
for i in range(100):
count += 1
elevations = elevation_function(df, lat_column='lat', long_column='lon')
end = time.time()
print(str(round(end - start)))
简化功能并添加错误处理:
elevation_function
需要编写才能与 pandas.DataFrame.apply
一起使用
- 使用
apply
,配合axis=1
,自动遍历每一行坐标
新功能:
make_remote_request
会不断的发出请求,直到得到response
.
- 更改异常以适应服务器返回的异常(例如
except (OSError, urllib3.exceptions.ProtocolError) as error
)
- 可选地,
import time
并在异常中的 continue
之前添加 time.sleep(5)
,以便与远程服务器配合使用。
def make_remote_request(url: str, params: dict) -> json:
"""
Makes the remote request
Continues making attempts until it succeeds
"""
count = 1
while True:
try:
response = requests.get((url + urllib.parse.urlencode(params)))
except (OSError, urllib3.exceptions.ProtocolError) as error:
print('\n')
print('*' * 20, 'Error Occured', '*' * 20)
print(f'Number of tries: {count}')
print(f'URL: {url}')
print(error)
print('\n')
count += 1
continue
break
return response
def eleveation_function(x):
url = 'https://nationalmap.gov/epqs/pqs.php?'
params = {'x': x[1],
'y': x[0],
'units': 'Meters',
'output': 'json'}
result = make_remote_request(url, params)
return result.json()['USGS_Elevation_Point_Query_Service']['Elevation_Query']['Elevation']
实现函数
import requests
import urllib
import urllib3
import pandas as pd
# coordinates with known elevation
lat = [48.633, 48.733, 45.1947, 45.1962]
lon = [-93.9667, -94.6167, -93.3257, -93.2755]
# create df
df = pd.DataFrame({'lat': lat, 'lon': lon})
lat lon
48.6330 -93.9667
48.7330 -94.6167
45.1947 -93.3257
45.1962 -93.2755
# apply the function
df['elevations'] = df.apply(eleveation_function, axis=1)
lat lon elevations
48.6330 -93.9667 341.14
48.7330 -94.6167 328.80
45.1947 -93.3257 262.68
45.1962 -93.2755 272.64
也可以通过以下方式传入参数:
PARAMS = {'x':x[1], 'y':x[0], 'units':'Feet', 'output':'json'}
r = requests.get(url = URL, params = PARAMS)
我有一个 python 脚本,我从这个 question 中获得了该脚本,该脚本将从 USGS 高程点查询服务中提取。但是,它一直超时,并在看似随机的时间后和我的查询完成之前将我踢出局。我需要另一种方法来在给定经纬度坐标的情况下提取高程数据。
这是我当前的查询:
# ========= pull elev from usgs server ======
# USGS POINT QUERY SERVICE ==================
url = r'https://nationalmap.gov/epqs/pqs.php?'
# ===========================================
# coordinates with known elevation
lat = [48.633, 48.733, 45.1947, 45.1962]
lon = [-93.9667, -94.6167, -93.3257, -93.2755]
# create df
df = pd.DataFrame({
'lat': lat,
'lon': lon
})
def elevation_function(df, lat_column, long_column):
elevations = []
counter = 0
start = time.time()
for lat, lon in zip(df[lat_column], df[long_column]):
# define rest query params
params = {
'output': 'json',
'x': lon,
'y': lat,
'units': 'Meters'
}
# format query string and return query value
result = requests.get((url + urllib.parse.urlencode(params)))
elevations.append(result.json()['USGS_Elevation_Point_Query_Service']['Elevation_Query']['Elevation'])
counter += 1
print('Proportion of job complete: {}'.format(round(counter/df.shape[0],3)))
end = time.time()
print(str(round(end - start)) + " seconds into job\n")
df['elev'] = elevations
return elevations
start = time.time()
count = 0
for i in range(100):
count += 1
elevations = elevation_function(df, lat_column='lat', long_column='lon')
end = time.time()
print(str(round(end - start)))
简化功能并添加错误处理:
elevation_function
需要编写才能与pandas.DataFrame.apply
一起使用- 使用
apply
,配合axis=1
,自动遍历每一行坐标
- 使用
新功能:
make_remote_request
会不断的发出请求,直到得到response
.- 更改异常以适应服务器返回的异常(例如
except (OSError, urllib3.exceptions.ProtocolError) as error
) - 可选地,
import time
并在异常中的continue
之前添加time.sleep(5)
,以便与远程服务器配合使用。
def make_remote_request(url: str, params: dict) -> json:
"""
Makes the remote request
Continues making attempts until it succeeds
"""
count = 1
while True:
try:
response = requests.get((url + urllib.parse.urlencode(params)))
except (OSError, urllib3.exceptions.ProtocolError) as error:
print('\n')
print('*' * 20, 'Error Occured', '*' * 20)
print(f'Number of tries: {count}')
print(f'URL: {url}')
print(error)
print('\n')
count += 1
continue
break
return response
def eleveation_function(x):
url = 'https://nationalmap.gov/epqs/pqs.php?'
params = {'x': x[1],
'y': x[0],
'units': 'Meters',
'output': 'json'}
result = make_remote_request(url, params)
return result.json()['USGS_Elevation_Point_Query_Service']['Elevation_Query']['Elevation']
实现函数
import requests
import urllib
import urllib3
import pandas as pd
# coordinates with known elevation
lat = [48.633, 48.733, 45.1947, 45.1962]
lon = [-93.9667, -94.6167, -93.3257, -93.2755]
# create df
df = pd.DataFrame({'lat': lat, 'lon': lon})
lat lon
48.6330 -93.9667
48.7330 -94.6167
45.1947 -93.3257
45.1962 -93.2755
# apply the function
df['elevations'] = df.apply(eleveation_function, axis=1)
lat lon elevations
48.6330 -93.9667 341.14
48.7330 -94.6167 328.80
45.1947 -93.3257 262.68
45.1962 -93.2755 272.64
也可以通过以下方式传入参数:
PARAMS = {'x':x[1], 'y':x[0], 'units':'Feet', 'output':'json'}
r = requests.get(url = URL, params = PARAMS)