将地理坐标从度数转换为十进制
Posted
技术标签:
【中文标题】将地理坐标从度数转换为十进制【英文标题】:Converting geo coordinates from degree to decimal 【发布时间】:2013-01-02 11:57:27 【问题描述】:我想将我的地理坐标从度数转换为小数,我的数据如下:
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】:使用 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
【讨论】:
这可能是最简单的解决方案(您还可以免费获得其他坐标转换)。我只想补充一点,该功能现在已移至measurements
包中,并且在 birk
中已弃用。【参考方案2】:
尝试使用sp
库中的char2dms
函数。它还有其他功能可以额外进行十进制转换。
library("sp")
?char2dms
【讨论】:
如果您想将"35d8'2.222\"E"
之类的内容转换为35.13395
,请将输出包装在as.numeric()
中。您将需要尾随指南针方向。【参考方案3】:
一些向量化和矩阵操作将使您的函数更简单:
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
免责声明:我没有检查你的数学。自行决定使用。
【讨论】:
正如对问题的评论所指出的,输入是度数和小数分钟,而不是度数、分钟和秒。如果您仅在°
上拆分并删除 z[3, ]/3600
部分,则此答案有效。【参考方案4】:
感谢@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
【讨论】:
【参考方案5】:查看OSMscale
包中的命令degree
。
【讨论】:
这是对我来说效果更好的答案。非常感谢!查看帮助文件中的一些示例:``` d 【参考方案6】:正如 Jim Lewis 在您使用浮点分钟之前评论的那样。然后你只在
上连接两个元素dec=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)
添加负坐标的替代方案,对我很有用。我仍然不明白为什么 sp
库中的 char2dms
函数对我不起作用。
谢谢
【讨论】:
【参考方案7】:另一个不太优雅的选项使用 substring 而不是 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))
【讨论】:
以上是关于将地理坐标从度数转换为十进制的主要内容,如果未能解决你的问题,请参考以下文章