Conversión de coordenadas geográficas de grado a decimal

Quiero convertir mis coordenadas geográficas de grados a decimales, mis datos son los siguientes:

lat long 105252 30°25.264 9°01.331 105253 30°39.237 8°10.811 105255 31°37.760 8°06.040 105258 31°41.190 8°06.557 105259 31°41.229 8°06.622 105260 31°38.891 8°06.281 

Tengo este código pero no puedo ver por qué no funciona:

 convert<-function(coord){ tmp1=strsplit(coord,"°") tmp2=strsplit(tmp1[[1]][2],"\\.") dec=c(as.numeric(tmp1[[1]][1]),as.numeric(tmp2[[1]])) return(dec[1]+dec[2]/60+dec[3]/3600) } don_convert=don1 for(i in 1:nrow(don1)){don_convert[i,2]=convert(as.character(don1[i,2])); don_convert[i,3]=convert(as.character(don1[i,3]))} 

La función de conversión funciona, pero el código en el que le pido al bucle que haga el trabajo por mí no funciona.

Cualquier sugerencia es apperciated.

Utilice el paquete de medidas de CRAN que ya tiene una función de conversión de unidades para que no tenga que hacer la suya propia:

 x = read.table(text = " lat long 105252 30°25.264 9°01.331 105253 30°39.237 8°10.811 105255 31°37.760 8°06.040 105258 31°41.190 8°06.557 105259 31°41.229 8°06.622 105260 31°38.891 8°06.281", header = TRUE, stringsAsFactors = FALSE) 

Una vez que su data.frame está configurado, entonces:

 # change the degree symbol to a space x$lat = gsub('°', ' ', x$lat) x$long = gsub('°', ' ', x$long) # convert from decimal minutes to decimal degrees x$lat = measurements::conv_unit(x$lat, from = 'deg_dec_min', to = 'dec_deg') x$long = measurements::conv_unit(x$long, from = 'deg_dec_min', to = 'dec_deg') 

Resultando en el producto final:

  lat long 105252 30.4210666666667 9.02218333333333 105253 30.65395 8.18018333333333 105255 31.6293333333333 8.10066666666667 105258 31.6865 8.10928333333333 105259 31.68715 8.11036666666667 105260 31.6481833333333 8.10468333333333 

Intenta usar la función char2dms en la biblioteca sp . Tiene otras funciones que también harán conversión decimal.

 library("sp") ?char2dms 

Un poco de vectorización y manipulación de la matriz simplificará su función:

 x <- read.table(text=" lat long 105252 30°25.264 9°01.331 105253 30°39.237 8°10.811 105255 31°37.760 8°06.040 105258 31°41.190 8°06.557 105259 31°41.229 8°06.622 105260 31°38.891 8°06.281", header=TRUE, stringsAsFactors=FALSE) x 

La función en sí misma hace uso de:

  • strsplit() con el patrón de strsplit() regulares "[°\\.]" - esto hace que la cadena se divida en un solo paso
  • sapply para recorrer el vector

Prueba esto:

 convert<-function(x){ z <- sapply((strsplit(x, "[°\\.]")), as.numeric) z[1, ] + z[2, ]/60 + z[3, ]/3600 } 

Intentalo:

 convert(x$long) [1] 9.108611 8.391944 8.111111 8.254722 8.272778 8.178056 

Descargo de responsabilidad: no verifiqué tus cálculos. Use a su propia discreción.

Como Jim Lewis comentó antes, parece que estás usando minutos de coma flotante. Entonces solo concatenas dos elementos en

dec = c (as.numeric (tmp1 [[1]] [1]), as.numeric (tmp2 [[1]]))

Teniendo grados, minutos y segundos en la forma 43 ° 21’8.02 que como as.character() devuelve “43 ° 21’8.02 \” “, actualicé tu función a

 convert<-function(coord){ tmp1=strsplit(coord,"°") tmp2=strsplit(tmp1[[1]][2],"'") tmp3=strsplit(tmp2[[1]][2],"\"") dec=c(as.numeric(tmp1[[1]][1]),as.numeric(tmp2[[1]][1]),as.numeric(tmp3[[1]])) c<-abs(dec[1])+dec[2]/60+dec[3]/3600 c<-ifelse(dec[1]<0,-c,c) return(c) } 

agregando la alternativa para coordenadas negativas, y funciona muy bien para mí. Todavía no entiendo por char2dms función char2dms en la biblioteca sp no funcionó para mí.

Gracias

Otra opción menos elegante que utiliza subcadena en lugar de strsplit. Esto solo funcionará si todas sus posiciones tienen la misma cantidad de dígitos. Para las coordenadas negativas simplemente multiplique por -1 para el grado decimal correcto.

 x$LatDD<-(as.numeric(substring(x$lat, 1,2)) + (as.numeric(substring(x$lat, 4,9))/60)) x$LongDD<-(as.numeric(substring(x$long, 1,1)) + (as.numeric(substring(x$long, 3,8))/60)) 

Gracias por las respuestas de @Gord Stephen y @CephBirk. Seguro me ayudó. Pensé que solo mencionaría que también encontré que las measurements::conv_unit no tratan con las entradas “E / W” “N / S”, sino que requieren grados positivos / negativos. Mis coordenadas vienen como cadenas de caracteres "1 1 1W" y deben convertirse primero en "-1 1 1" .
Pensé que compartiría mi solución para eso.

 df <- c("1 1 1E", "1 1 1W", "2 2 2N","2 2 2S") measurements::conv_unit(df, from = 'deg_min_sec', to = 'dec_deg') [1] "1.01694444444444" NA NA NA Warning message: In split(as.numeric(unlist(strsplit(x, " "))) * c(3600, 60, 1), : NAs introduced by coercion ewns <- ifelse( str_extract(df,"\\(?[EWNS,.]+\\)?") %in% c("E","N"),"+","-") dms <- str_sub(df,1,str_length(df)-1) df2 <- paste0(ewns,dms) df_dec <- measurements::conv_unit(df2, from = 'deg_min_sec', to = 'dec_deg')) df_dec [1] "1.01694444444444" "-1.01694444444444" "2.03388888888889" "-2.03388888888889" as.numeric(df_dec) [1] 1.016944 -1.016944 2.033889 -2.033889 

Eche un vistazo al degree comando en el paquete OSMscale .