如何将度分秒转换为度小数

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#将度分秒(° ‘ “)转换度(°)程序实现(附源码)

测绘程序设计C#将度分秒(° ‘ “)转换度(°)程序实现(附源码)

如何将度转换为弧度,弧度转换为度

怎么把度数化成度分秒

excel将小数格式转化为分秒毫秒格式

第十二周oj题目将度分秒转换为弧度