Arturo Sbr
Arturo Sbr

Reputation: 6333

Convert DMS coordinates to decimal degrees in R

I have the following coordinates in DMS format. I need to convert them to decimal degrees.

# Libraries
> library(sp)
> library(magrittr)

# Latitide & Longitude as strings
> lat <- '21d11m24.32s'
> lng <- '104d38m26.88s'

I tried:

> lat_d <- char2dms(lat, chd='d', chm='m', chs='s') %>% as.numeric()
> lng_d <- char2dms(lng, chd='d', chm='m', chs='s') %>% as.numeric()

> print(c(lat_d, lng_d))
[1]  21.18333 104.63333

Although close, this result is different from the output I get from this website. According to this site, the correct output should be:

Latitude: 21.190089

Longitude: 104.6408

It seems that sp::char2dms and as.numeric are rounding the coordinates. I noticed this issue when converting a large batch of DMS coordinates using this method because the number of unique values decreases drastically after the conversion.

Upvotes: 7

Views: 7508

Answers (2)

Anthony Basooma
Anthony Basooma

Reputation: 21

The most simple and straight-forward approach is using parzer library.

For example, given points

> library(parzer)
> 
> latitude <- "40°14'55.5"
> longitude <- "19°58'22.7"

Note: direction not required

> lat_out <- parzer::parse_lat(latitude)
> print(lat_out)
[1] 40.24875
> 
> lon_out <- parzer::parse_lat(longitude)
> print(lon_out)
[1] 19.97297
> 

Proof for converting dms to decimal is based on formular degress+(minutes/60)+(seconds/3600)

> latproof = 40+(14/60)+(55.5/3600)
> print(latproof)
[1] 40.24875
> 
> lonproof = 19+(58/60)+(22.7/3600)
> print(lonproof)
[1] 19.97297

For more information, check https://semba-blog.netlify.app/02/25/2020/geographical-coordinates-conversion-made-easy-with-parzer-package-in-r/

Upvotes: 0

lovalery
lovalery

Reputation: 4652

You are right! To tell you the truth, I didn't notice this problem. To get around this, here is a solution with the use of the package measurements:

REPREX:

install.packages("measurements") 
library(measurements)

lat <- conv_unit('21 11 24.32', from = "deg_min_sec", to = "dec_deg")
long <- conv_unit('104 38 26.88' , from = "deg_min_sec", to = "dec_deg")

print(c(lat, long))
#> [1] "21.1900888888889" "104.6408"

Created on 2021-10-07 by the reprex package (v2.0.1)


Edit from OP

This can also be solved by adding 'N' or 'S' to latitude and 'E' or 'W' to longitude.

# Add character to lat & long strings
> lat_d <- char2dms(paste0(lat,'N'), chd='d', chm='m', chs='s') %>% as.numeric()
> lng_d <- char2dms(paste0(lng,'W'), chd='d', chm='m', chs='s') %>% as.numeric()
> print(c(lat_d, lng_d))
[1]   21.19009 -104.64080

Upvotes: 7

Related Questions