1

So I've been shared a dataset with what to me is an unusual format for degree min second data. In their own words:

    The coordinates provided are longitude and latitude in degrees minutes and seconds.
    So for example, coordinates recorded in the spreadsheet as 
    X_Long: -10.0135 Y_Lat:  53.5726, can be taken as Longitude: 10º 01'35" W, 
    Latitude: 53º 57'26" N using standard notation.

I need to get this into decimal. Any quick way to do this ?

Edit:

in trying to solve this I made a following code:

    # Fake data
    X_Long <- as.numeric(c(-2.4564, -1.0134, -8.01))

    long.temp <- abs(X_Long - trunc(X_Long))
    long.min <- trunc(long.temp*100)
    long.sec <- trunc(as.integer((long.temp*100 - long.min)*100))

Its giving me weird rounding errors:

    > X_Long
    [1] -2.4564 -1.0134 -8.0100
    > long.temp
    [1] 0.4564 0.0134 0.0100
    > long.min
    [1] 45  1  0
    > long.sec
    [1] 63 34 99

This seems to be coming from the trunc function - compare results here

    > long.temp*100
    [1] 45.64  1.34  1.00
    > trunc(long.temp*100)
    [1] 45  1  0

Anyone know why this is happening ?

  • See here – rcs Apr 23 '14 at 9:11
  • I have - it doesn't help me. This format doens't have helpful markers between minutes and seconds. I'm having a hard time teasing them apart. I had some code I thought would work but I found a bug - will edit main question – unsure.person Apr 23 '14 at 9:31
  • This is FAQ 7.31 format(abs(-8.01 - trunc(-8.01))*100, digits = 16) – mdsumner Apr 23 '14 at 11:49
  • Sorry i don't follow you - what FAQ- do you have a link ? – unsure.person Apr 23 '14 at 13:15
1

How about:

fun <- function(x, ...) {
   ## determine sign, this complicates the whole thing 
   sgn <- grepl("^-", x)
   ## split on the "." separator
   parts <- strsplit(x, "\\.")
   ## extract the minute/seconds digits, convert to numeric, scale, and sign
   ifelse(sgn, -1, 1) * sapply(parts, function(x)   sum(abs(as.numeric(c(x[1L], substr(x[2L], 1, 2), substr(x[2L], 3, 5))) / c(1, 60, 3600))))
}

The code would be a lot neater without having to find the sign up front and apply it to the sum. (Well I can't see a neater way).

fun("-10.0135")
[1]  -10.02639

fun("53.5726")
[1] 53.95722

It's vectorized:

fun(c("-10.0135", "53.5726", "-35.0020"))
[1] -10.02639  53.95722 -35.00556

You probably want checks for sensible inputs, treating lon/lat separately etc.

Check round-tripping (here we have to separate for lon/lat)

  require(sp)
  dd2dms(fun("-10.0135"))
  [1] 10d1'35"W

  dd2dms(fun(c("53.5726", "-35.0020")), NS = TRUE)
  [1] 53d57'26"N 35d0'20"S 
  • thx but my fake data above breaks it fun(as.character(X_Long)) [1] -2.767778 -1.026111 NA – unsure.person Apr 23 '14 at 10:02
  • Well if you are coercing numeric to character you'll need to get the formatting right, as it stands with your edit the question is kind of open-ended now. – mdsumner Apr 23 '14 at 10:06
  • Yeah I guess there are two questions now - but I just want anything that will work. The edit was my own attempt at being clever but I guess it didn't work :( I can probably fix the formatting inside excel - i.e. just fix it to show 4 decimals always and export as csv – unsure.person Apr 23 '14 at 10:34
  • Well it depends on the need, my function can be changed to be more flexible, but if you have numeric input there are many more cases to catch. It should not be numeric ever if the format is taken seriously, perhaps Excel is the main problem. – mdsumner Apr 23 '14 at 10:38
  • Ha this insane format is the main problem :) Actually just talking to you it occurs to me I could do all this conversion in excel - not ideal but I'd have it done by now. I'm still puzzled by the weird rounding errors I had with the trunc function above – unsure.person Apr 23 '14 at 11:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.