2013-01-18 61 views
13

我想我的地理坐标从度到小数转换,我的数据如下:转换地理距离度坐标转换为十进制

  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 

我有这样的代码,但我不明白为什么它不工作:

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]))} 

转换函数的工作原理,但我要求循环为我做这项工作的代码不起作用。

任何建议都可以解决。

+1

它看起来像转换功能期望度,分钟和秒,但你的输入似乎有度和浮点分钟,没有秒字段。它看起来并不像正确处理负值。但不确定这些问题是否与您的问题有关。 –

回答

4

矢量和矩阵操作的一点会让你的功能要简单得多:

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 

函数本身利用了:

  • strsplit()与正则表达式模式"[°\\.]" - 这确实字符串分割在一个步骤中
  • sapply以遍历载体

试试这个:

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

试试:

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

免责声明:我没有检查你的数学。自行决定使用。

5

尝试使用sp库中的char2dms函数。它还有其他功能,将额外做十进制转换。

library("sp") 
?char2dms 
0

正如Jim Lewis评论之前似乎您使用的是浮点分钟。然后,你只串连上

癸= C两个元件(as.numeric(TMP1 [[1]] [1]),as.numeric(TMP2 [[1]]))

有度,分,秒的形式43°21'8.02这as.character()返回“43°21'8.02 \””我是你的功能更新,以

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) 
} 

增加对负坐标的选择,以及伟大工程我仍然没有得到为什么char2dms功能在sp库二不为我工作。

谢谢

0

另一个不太优雅的选项使用子字符串,而不是strsplit。这只有在您的所有职位都有相同的数字位数时才有效。对于负坐标,正确的小数点乘以-1。

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)) 
12

使用来自CRAN的measurements包,它已经具备了单元转换功能,所以你不需要让自己:

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) 

一旦你的data.frame设置则:

# 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') 

中端产品所造成:

    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 
+1

这可能是最简单的解决方案(也可以免费获得其他坐标转换)。我只想补充一点,现在这个功能已经被移动到'measurements'包中,并且在'birk'中被弃用。 –

+0

谢谢戈德!我忘了更新这个。 – CephBirk

0

感谢@Gord Stephen和@CephBirk的回答。当然帮助我。 我想我只是提到,我还发现measurements::conv_unit不处理“E/W”“N/S”条目,它需要积极/消极的程度。我的坐标是字符串"1 1 1W",需要先转换为"-1 1 1"
我想我会分享我的解决方案。

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