如何将度分秒转换为度小数
Posted
技术标签:
【中文标题】如何将度分秒转换为度小数【英文标题】:How to convert degree minute second to degree decimal 【发布时间】:2015-11-30 11:18:20 【问题描述】:我使用这种格式从 GPS 接收纬度和经度:
纬度:78°55'44.29458"N
我需要将此数据转换为:
纬度:78.9288888889
我在这里找到了这段代码:link
import re
def dms2dd(degrees, minutes, seconds, direction):
dd = float(degrees) + float(minutes)/60 + float(seconds)/(60*60);
if direction == 'E' or direction == 'S':
dd *= -1
return dd;
def dd2dms(deg):
d = int(deg)
md = abs(deg - d) * 60
m = int(md)
sd = (md - m) * 60
return [d, m, sd]
def parse_dms(dms):
parts = re.split('[^\d\w]+', dms)
lat = dms2dd(parts[0], parts[1], parts[2], parts[3])
return (lat)
dd = parse_dms("78°55'44.33324"N )
print(dd)
适用于这种格式
dd = parse_dms("78°55'44.33324'N" )
但它不适用于我的 datafromat。谁能帮我解决这个问题?
【问题讨论】:
【参考方案1】:这是我的一个班轮(很好,很好——也许是两行):)
import re
lat = '''51°36'9.18"N'''
deg, minutes, seconds, direction = re.split('[°\'"]', lat)
(float(deg) + float(minutes)/60 + float(seconds)/(60*60)) * (-1 if direction in ['W', 'S'] else 1)
这会输出51.60255
【讨论】:
【参考方案2】:上面的函数(dms2dd)不正确。
实际(有错误):
如果方向 == 'E' 或方向 == 'N': dd *= -1
修正条件:
如果方向 == 'W' 或方向 == 'S': dd *= -1
【讨论】:
【参考方案3】:问题在于秒 44.29458 在.
处拆分。
您可以直接定义分割字符(而不是 not 分割):
>>> re.split('[°\'"]+', """78°55'44.29458"N""")
['78', '55', '44.29458', 'N']
或保持正则表达式不变并合并第 2 部分和第 3 部分:
dms2dd(parts[0], parts[1], parts[2] + "." + parts[3], parts[4])
更新:
您的方法调用dd = parse_dms("78°55'44.33324"N )
是语法错误。添加关闭 "
并转义另一个。或者对字符串定义使用三重引号:
parse_dms("""78°55'44.29458"N""")
【讨论】:
当我在代码中添加第二个选项时仍然无法正常工作 嗯,如果你像parse_dms("78°55'44.33324"N )
这样调用你的函数,那就是语法错误。你需要像我一样传递字符串:parse_dms("""78°55'44.29458"N""")
。或者,您可以转义 "78°55'44.29458\"N"
或 '78°55\'44.29458"N'
等引号。有关更多详细信息,您应该查看在 Python 中定义字符串的语法。
啊,好吧,现在我明白了。谢谢法尔科:)
如果我有一个包含大量此类坐标的数组,那么如何通过此函数进行转换?【参考方案4】:
我知道这是一个老问题,但对于任何关注的人,我只是想指出您的 dms2dd()
函数中关于小数符号的逻辑似乎不正确。你有:
if direction == 'E' or direction == 'N':
dd *= -1
但只有当方向是本初子午线的西 (W) 或赤道的南 (S) 时,它才应该是负数。所以应该是:
if direction == 'W' or direction == 'S':
dd *= -1
这是一份完整指南的引述:https://www.ubergizmo.com/how-to/read-gps-coordinates/
纬线的坐标代表北 赤道,因为它是正的。如果数字是负数,它 代表赤道以南。
[...] 经线坐标代表东 本初子午线,因为它是积极的。如果数字是负数,它 代表本初子午线以西。
【讨论】:
【参考方案5】:你可以使用这个模块https://pypi.org/project/dms2dec/
将 DMS 转换为十进制。
用法
from dms2dec.dms_convert import dms2dec
dms2dec('''36°44'47.69"N''') # converts to dec
dms2dec('''3° 2'33.53"E''') # converts to dec
【讨论】:
【参考方案6】:我稍微修改了re:
parts = re.split('[^\d\w\.]+', dms)
正如@Falko 建议的那样,您可以使用双双引号或转义引号字符
parse_dms("53°19\'51.8\"N")
【讨论】:
【参考方案7】:对于多个坐标,您可以使用 pandas 读取它们。格式很重要——不应该有任何空格。可以使用替换功能删除空格。输出可以很容易地保存为文本文件或电子表格。我只是将它们打印出来进行验证,并将小数点四舍五入到 4。
### read input file
df = pd.read_excel('dms.xlsx')
n = len(df)
for i in range(n):
Lat_d = round(parse_dms(df.Lat[i].replace(" ", "")),4)
Long_d = round(parse_dms(df.Long[i].replace(" ", "")),4)
print(Lat_d, Long_d)
【讨论】:
【参考方案8】:如果您的数据在 DataFrame 中,您可以使用库 DataPrep 中的函数 clean_lat_long()
。使用 pip install dataprep
安装 DataPrep。
from dataprep.clean import clean_lat_long
df = pd.DataFrame("Latitude": ["78°55'44.29458''N", "51°36'9.18''N"])
df2 = clean_lat_long(df, lat_col="Latitude")
Latitude Latitude_clean
0 78°55'44.29458''N 78.9290
1 51°36'9.18''N 51.6026
【讨论】:
以上是关于如何将度分秒转换为度小数的主要内容,如果未能解决你的问题,请参考以下文章
测绘程序设计C#将度分秒(° ‘ “)转换度(°)程序实现(附源码)