lonsex2dec, latsex2dec

I need help with the function "lonsex2dec" and "latsex2dec" when working with several data.

I need to transform several data from a list from sexagesimal to decimal. I have 4 lists of one column and several rows. One list is for the directions, other for the degrees, another for the minutes and the last one for the seconds. The issue is that when using "lonsex2dec" or "latsex2dec", Rstudio returns me this information: "Error in FUN(left, right) : non-numeric argument to binary operator
In addition: Warning message:
In if (direction == "E") { :
the condition has length > 1 and only the first element will be used"
The script I have written is:
"mutate(longitud_final=lonsex2dec(lonf_degree,lonf_minute,lonf_second,lonf_dir))"
Where "lonf_degree" is the table for the degrees, "lonf_minute" the table for the minutes, "lonf_second" the table for the seconds and "lonf_dir" the table for the directions. All tables have 1 variable, 1 column and 54614 rows.

Hi!

To help us help you, could you please prepare a reproducible example (reprex) illustrating your issue? Please have a look at this guide, to see how to create one:

install.packages("dplyr")
install.packages("tidyr")
install.packages("ggplot2")
install.packages("pipeR")
install.packages("reshape")
install.packages("chron")
install.packages("readxl")
install.packages("vmsbase")
install.packages("trip")
install.packages("maptools")
install.packages("stringr")
install.packages("datapasta")
install.packages("reprex")
library(stringr)
library(dplyr)
library(tidyr)
library(ggplot2)
library(pipeR)
library(reshape)
library(chron)
library(readxl)
library(vmsbase)
library(trip)
library(maptools)
longitud<- read_xlsx("test.xlsx")
data.frame(stringsAsFactors=FALSE,
Direction = c("E", "E", "W"),
Degreee = c(9, 144, 0),
Minute = c(13, 14, 2),
Second = c(49, 36, 45)
)
direction<-select(longitud,1)
degree<-select(longitud,2)
minute<-select(longitud,3)
second<-select(longitud,4)
longitud_dec<-lonsex2dec(degree,minute,second,direction)

reprex::reprex()

Well, that is not actually a reprex, you are including a lot of unneeded packages and not making your issue clear enough. I think a proper minimal reproducible example for your problem would be similar to this (although I can't actually test it because I don't want to install vmsbase in my own machine and it is not possible to install it on RStudio Cloud because of its system dependencies).

library(dplyr)
library(vmsbase)

sample_data <- data.frame(stringsAsFactors = FALSE,
                          Direction = c("E", "E", "W"),
                          Degree = c(9, 144, 0),
                          Minute = c(13, 14, 2),
                          Second = c(49, 36, 45)
)

sample_data %>% 
  mutate(longitud_final = lonsex2dec(Degree, Minute, Second, Direction))

If you look up lonsex2dec in the vmbase package (vmsbase source: R/lonsex2dec.R) it doesn't look like that function vectorizes the sexagesimal to decimal operation.

Taking a tidyverse crack at it;

library(dplyr)
temp <- data.frame(stringsAsFactors=FALSE,
           Direction = c("E", "E", "W"),
           Degree = c(9, 144, 0),
           Minute = c(13, 14, 2),
           Second = c(49, 36, 45)
)


lonsex2dec <- function(degree, minute, second, direction) {
  declon = if_else(
    condition = (direction == "E"),
    true =  (degree + (minute / 60) + (second / 3600)),
    false = -(degree + (minute / 60) + (second / 3600))
  )
  return(declon)
}
  
 
temp <- temp %>% 
  mutate(
    decimal = lonsex2dec(
      Degree,Minute,Second,Direction
    )  
  )

temp
#>   Direction Degree Minute Second      decimal
#> 1         E      9     13     49   9.23027778
#> 2         E    144     14     36 144.24333333
#> 3         W      0      2     45  -0.04583333

Created on 2019-09-16 by the reprex package (v0.2.1)

Not totally sure that's how you are supposed to handle the direction argument. Online discussions (astronomy - Convert sexagesimal to decimal - Physics Stack Exchange) ignore direction completely. But I'll take their word for it.

1 Like

Yes, that example summarizes my issue (sorry for not doing it right, it's the 1st time I use RStudio)
As you can see if you try it, a warning message is shown in the console screen "In if (direction == "E") {:
the condition has length > 1 and only the first element will be used"
It is apparently something about mixing letters, numbers and managing several data at the same time. I guess there is some way of telling "lonsex2dec" function that it is going to work with a table of data and it has to take the data row by row

Hi @PalomaLlorente! Perhaps this wasn't clear, but I think that's exactly what @EconomiCurtis meant by saying:

A vectorized function in R terminology is one that can operate on an entire vector of values, rather than needing to be fed values one at a time. @EconomiCurtis's answer gives one example of how to write a vectorized version of lonsex2dec.

1 Like

I have tried your script and it works. However, now that I have introduced all the rows (more than 54000) the console shows a new warning message: " Error in FUN (left, right): non-numeric argument to binary operator " when running last "mutate". I haven´t been able to check if that is related to the function or is about the data I am introducing

Thank you very much for your help.

You can use vmsbase::lonsex2dec inside mutate(), you just have to do it row wise, see this example

library(dplyr)
# library(vmsbase)

# I don't want to install the package so I'm declaring the function as it is on vmsbase to test 
# my code, you wouldn't have to do this since you already have the package installed.
lonsex2dec <- function(degree, minute, second, direction) {
    if (direction == "E") {
        declon <- degree + (minute / 60) + (second / 3600)
    } else {
        declon <- -(degree + (minute / 60) + (second / 3600))
    }
    return(declon)
}

sample_data <- data.frame(stringsAsFactors = FALSE,
                          Direction = c("E", "E", "W"),
                          Degree = c(9, 144, 0),
                          Minute = c(13, 14, 2),
                          Second = c(49, 36, 45)
)

sample_data %>% 
    rowwise() %>% 
    mutate(longitud_final = lonsex2dec(Degree, Minute, Second, Direction)) %>% 
    ungroup()
#> # A tibble: 3 x 5
#>   Direction Degree Minute Second longitud_final
#>   <chr>      <dbl>  <dbl>  <dbl>          <dbl>
#> 1 E              9     13     49         9.23  
#> 2 E            144     14     36       144.    
#> 3 W              0      2     45        -0.0458
1 Like