将含度分秒(DMS)坐标的Pandas DataFrame转换为十进制度
如何将Pandas中的度分秒(DMS)经纬度转换为十进制度
当然有简便的实现办法啦!我平时处理地理数据时经常用到这个转换逻辑,下面给你一步步拆解怎么做:
核心转换逻辑
度分秒转十进制度的公式很直观:
十进制度 = 度 + 分/60 + 秒/3600
然后根据半球方向调整正负:
- 北纬(N)、东经(E):保持正值
- 南纬(S)、西经(W):转为负值
具体实现步骤
1. 编写DMS转十进制的函数
我们可以用正则表达式精准提取DMS字符串里的度、分、秒和方向符号,再计算十进制值,同时处理空值或无效格式的情况:
import re import pandas as pd def dms_to_decimal(dms_str): # 处理空值或类似"..."的无效内容 if pd.isna(dms_str) or "..." in str(dms_str): return pd.NA # 匹配度、分、秒和方向的正则模式 match = re.match(r'(\d+)°(\d+)\'(\d+\.\d+)"([NSEW])', str(dms_str)) if not match: return pd.NA # 提取各组数据并转换类型 degrees = int(match.group(1)) minutes = int(match.group(2)) seconds = float(match.group(3)) direction = match.group(4) # 计算十进制基础值 decimal = degrees + minutes/60 + seconds/3600 # 根据半球方向调整正负 if direction in ['S', 'W']: decimal = -decimal return round(decimal, 6) # 保留6位小数,可按需调整
2. 应用函数到DataFrame列
接下来把这个函数批量应用到你的经纬度列上,这里用你提供的示例数据来演示:
# 构建示例DataFrame(注意转义字符串里的引号) data = { "母公司(Parent Company)": ["Incasi Raya"]*6, "CPO": ["X"]*6, "PKO": [""]*6, "Latitude(纬度)": ['0°51\'56.29"S', '1°23\'39.29"S', '0°19\'56.63"N', '0°21\'45.91"N', '1°41\'6.56"S', '1°15\'2.13"S'], "Longitude(经度)": ['101°26\'46.29"E', '101°35\'30.45"E', '99°22\'56.36"E', '99°37\'59.68"E', '102°14\'7.68"E', '...'] } df = pd.DataFrame(data) # 批量转换经纬度列 df["Latitude_Decimal"] = df["Latitude(纬度)"].apply(dms_to_decimal) df["Longitude_Decimal"] = df["Longitude(经度)"].apply(dms_to_decimal) # 查看转换后的结果 print(df[["Latitude(纬度)", "Latitude_Decimal", "Longitude(经度)", "Longitude_Decimal"]])
3. 转换结果示例
运行代码后,你会得到类似这样的输出:
| Latitude(纬度) | Latitude_Decimal | Longitude(经度) | Longitude_Decimal |
|---|---|---|---|
| 0°51'56.29"S | -0.865636 | 101°26'46.29"E | 101.446192 |
| 1°23'39.29"S | -1.394247 | 101°35'30.45"E | 101.591792 |
| 0°19'56.63"N | 0.332397 | 99°22'56.36"E | 99.382322 |
| ... | ... | ... | ... |
额外提示
- 如果你的DMS格式有微小差异(比如秒数没有小数点、空格位置不同),可以微调正则表达式来适配
- 对于超大数据集,
apply已经足够高效;如果追求极致性能,可以考虑用矢量化操作进一步优化
内容的提问来源于stack exchange,提问作者Funkeh-Monkeh




