rgpsarcgisdata-conversion

How to change decimal points in GPS coordinates to DMS (degrees, minutes, seconds) using R


Problem:

I have a data frame containing GPS coordinates where instead of using the symbols for degrees and minutes, they are written in the format where decimal points have been used instead, which is incorrect:

enter image description here

I'd like to convert all the GPS coordinates into DMS (degrees, minutes, seconds), whereby all the coordinates are written in this format:

27°57'67.9, 33°88'02.7

It's quite labour-intensive to manually revert all the GPS coordinates individually as the coordinates are written in two separate columns with over 800 rows.

I can't figure out how to do this conversion where I can add the symbols for degrees (°), and minutes (') to all the coordinates in my data frame using R.

In my data frame, some of the GPS positions are unknown and they are written in this format in the cells:

enter image description here

The code needs to recognise these missing GPS positions.

If anyone can help, I'd be deeply appreciative


Solution

  • Using the tidyverse and a helper function, this will achieve your desired output. I have included two versions of the repair_dms function. One is longhand to show the steps more clearly, the other is more concise and uses base R paste0() instead of stringr::str_c():

    library(dplyr)
    library(stringr)
    library(purrr)
    
    # Example df
    df <- data.frame(longitude = c("missed", "-127.57.679"),
                     latitude = c("missed", "133.88.027"))
    
    
    # Function to repair coordinates
    repair_dms <- function(x) {
      
      if (x %in% c("Missed", "missed")) { x } else {
      
      y <- str_split(x, "\\.", simplify = TRUE)
      
      d <- y[1]
      m <- y[2]
      s <- ifelse(ncol(y) == 3,
                  paste0(substr(y[3], 1, 2), ".",substr(y[3], 3, 3)), "0.0")
      
      repaired <- str_c(d, "°", m, "'", s)
      
      }
    }
    
    # Repair DMS coordinates
    df <- df |>
      mutate(longitude = map_chr(longitude, repair_dms),
             latitude = map_chr(latitude, repair_dms))
    
    df
    #      longitude    latitude
    # 1       missed      missed
    # 2 -127°57'67.9 133°88'02.7
    

    A more concise version of the repair_dms function:

    repair_dms <- function(x) {
      
      if (x %in% c("Missed", "missed")) { x } else {
      
      y <- str_split(x, "\\.", simplify = TRUE)
      s <- ifelse(ncol(y) == 3,
                  paste0(substr(y[3], 1, 2), ".",substr(y[3], 3, 3)), "0.0")
      repaired <- paste0(y[1], "°", y[2], "'", s)
      
      }
    }