将坐标从非常规格式的度数转换为十进制度数

Posted

技术标签:

【中文标题】将坐标从非常规格式的度数转换为十进制度数【英文标题】:Converting coordinates from degree with unconventional format to decimal degree 【发布时间】:2020-02-26 23:42:54 【问题描述】:

我正在尝试转换我的数据,以便它可以绘制在地图上。例如数据如下:

# A tibble: 2 x 2
  Latitud           Longitud        
  <chr>             <chr>           
1 10º 35' 28.98'' N 3º 41' 33.91'' O
2 10º 35' 12.63'' N 3º 45' 46.22'' O

我正在尝试使用以下方法对其进行变异:

df %>% 
  mutate(
    Latitud = str_replace_all(Latitud, "''", ""),
    lat_edit = sp::char2dms(Latitud), "°")

返回和错误:

Error in if (any(abs(object@deg) > 90)) return("abs(degree) > 90") : 
  missing value where TRUE/FALSE needed
In addition: Warning message:
In asMethod(object) : NAs introduced by coercion

我想在 ggplot(或其他空间包)的地图上绘制这两个点

数据:

structure(list(Latitud = c("40º 25' 25.98'' N", "40º 25' 17.63'' N"
), Longitud = c("3º 42' 43.91'' O", "3º 40' 56.22'' O")), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -2L))

【问题讨论】:

为什么你的经度以“O”结尾?这是英语以外的语言的缩写,还是我不熟悉的标记? 对不起!它是西方的 Oeste(西班牙语)。 好吧,这实际上是我的猜测。我将编辑我的答案,将字符串中的“O”替换为“W” 【参考方案1】:

您可以使用以下自定义函数(我假设NSWE。不确定O 在经度中的含义):

angle2dec <- function(angle) 
  angle <- as.character(angle)
  angle <- ifelse(grepl("S|W", angle), paste0("-", angle), angle)
  angle <- trimws(gsub("[^- +.0-9]", "", angle))
  x <- do.call(rbind, strsplit(angle, split=' '))
  x <- apply(x, 1L, function(y) 
    y <- as.numeric(y)
    (abs(y[1]) + y[2]/60 + y[3]/3600) * sign(y[1])
  )
  return(x)

应用于数据:

df1[] <- lapply(df1, angle2dec)

df1
#>     Latitud  Longitud
#> 1 -40.42388  3.712197
#> 2  40.42156 -3.682283

绘图:

library(ggplot2)

ggplot(df1, aes(x = Longitud, y = Latitud)) +
  geom_point()


对不同半球的数据稍作修改:

df1 <- structure(list(Latitud = c("40<U+623C><U+3E61> 25' 25.98'' S", 
                                  "40<U+623C><U+3E61> 25' 17.63'' N"), 
                      Longitud = c("3<U+623C><U+3E61> 42' 43.91'' E",
                                   "3<U+623C><U+3E61> 40' 56.22'' W")), 
                 class = c("tbl_df", "tbl", "data.frame"), 
                 row.names = c(NA, -2L))

参考Converting geo coordinates from degree to decimal。

【讨论】:

谢谢!它也适用于我的完整数据集。我会绘制它们并仔细检查位置,再次感谢! 谢谢!我今天将仔细查看答案并接受其中一个。 N - Norte, S - Sur, W - Oeste 和 E - Este 西班牙语。不过我会把它们改成英文。【参考方案2】:

我先说我直到现在才使用char2dms,所以我可能错过了一些错综复杂的问题(例如我上面关于"O" 作为方向的问题)。查看文档和示例,您需要给出用于划分度、分和秒的字符。在您的情况下,它们分别是 "º""'""''"。我跳过了删除其中第三个的步骤,因为有必要查看秒的写入位置。 (更新: 添加了将正则表达式 "O$" (oeste) 替换为 "W" (west) 的步骤)。这会让你得到以下内容:

library(dplyr)
library(ggplot2)
library(sp)

dat <- structure(list(Latitud = c("40º 25' 25.98'' N", "40º 25' 17.63'' N"
), Longitud = c("3º 42' 43.91'' O", "3º 40' 56.22'' O")), class = c("tbl_df", 
                                                                    "tbl", "data.frame"), row.names = c(NA, -2L)) %>%
  mutate_at(vars(Latitud, Longitud), stringr::str_replace_all, "O$", "W")

char2dms(dat$Latitud, chd = "º", chm = "'", chs = "''")
#> [1] 40d25'25.98"N 40d25'17.63"N

这是一个DMS S3 对象,而不是向量(我的知识到此结束),因此您不能将其直接放入数据框列中。相反,转换为数字向量,您的数据框中就有了数字坐标。

dat_numeric <- dat %>%
  mutate(lat_edit = as.numeric(char2dms(dat$Latitud, chd = "º", chm = "'", chs = "''")),
         lon_edit = as.numeric(char2dms(dat$Longitud, chd = "º", chm = "'", chs = "''")))

dat_numeric
#> # A tibble: 2 x 4
#>   Latitud           Longitud         lat_edit lon_edit
#>   <chr>             <chr>               <dbl>    <dbl>
#> 1 40º 25' 25.98'' N 3º 42' 43.91'' W     40.4    -3.71
#> 2 40º 25' 17.63'' N 3º 40' 56.22'' W     40.4    -3.68

像正常数字一样绘制:

ggplot(dat_numeric, aes(x = lon_edit, y = lat_edit)) +
  geom_point()

或转换为sf 对象并使用适当的纵横比、投影等进行绘图。

sf::st_as_sf(dat_numeric, coords = c("lon_edit", "lat_edit")) %>%
  ggplot() +
  geom_sf()

【讨论】:

以上是关于将坐标从非常规格式的度数转换为十进制度数的主要内容,如果未能解决你的问题,请参考以下文章

将gps坐标转换为距离并将距离转换为十进制度数的半径

php 在十进制坐标和度数坐标之间转换

将 DDM 转换为 DEC(十进制度)

将字符串度数转换为十进制单位[关闭]

python 脚本将以DMS(度数分钟秒)格式给出的坐标转换为DD(度数)

在 python 中输入精确度数