我找到了一个如何做到这一点的相当简单的例子,但我不能让它为我工作。我很擅长R
library(rgdal)
xy <- cbind(c(118, 119), c(10, 50))
project(xy, "+proj=utm +zone=51 ellps=WGS84")
[,1] [,2]
[1,] -48636.65 1109577
[2,] 213372.05 5546301
但这是示例数字。我有成千上万的坐标需要转换,我无法弄清楚如何将它们从我的表中转移到这个脚本中
我的数据集有3列,ID,X和Y.如何使用此等式转换它们?我已经坚持了几个星期
答案 0 :(得分:23)
为了确保在与坐标相关的每一步都有适当的投影元数据,我建议尽快将这些点转换为SpatialPointsDataFrame
对象。
有关如何将简单data.frames或矩阵转换为 SpatialPointsDataFrame 对象的更多信息,请参阅?"SpatialPointsDataFrame-class"
。
library(sp)
library(rgdal)
xy <- data.frame(ID = 1:2, X = c(118, 119), Y = c(10, 50))
coordinates(xy) <- c("X", "Y")
proj4string(xy) <- CRS("+proj=longlat +datum=WGS84") ## for example
res <- spTransform(xy, CRS("+proj=utm +zone=51 ellps=WGS84"))
res
# coordinates ID
# 1 (-48636.65, 1109577) 1
# 2 (213372, 5546301) 2
## For a SpatialPoints object rather than a SpatialPointsDataFrame, just do:
as(res, "SpatialPoints")
# SpatialPoints:
# x y
# [1,] -48636.65 1109577
# [2,] 213372.05 5546301
# Coordinate Reference System (CRS) arguments: +proj=utm +zone=51
# +ellps=WGS84
答案 1 :(得分:13)
将纬度和经度点转换为UTM
library(sp)
library(rgdal)
#Function
LongLatToUTM<-function(x,y,zone){
xy <- data.frame(ID = 1:length(x), X = x, Y = y)
coordinates(xy) <- c("X", "Y")
proj4string(xy) <- CRS("+proj=longlat +datum=WGS84") ## for example
res <- spTransform(xy, CRS(paste("+proj=utm +zone=",zone," ellps=WGS84",sep='')))
return(as.data.frame(res))
}
# Example
x<-c( -94.99729,-94.99726,-94.99457,-94.99458,-94.99729)
y<-c( 29.17112, 29.17107, 29.17273, 29.17278, 29.17112)
LongLatToUTM(x,y,15)
答案 2 :(得分:4)
在您的问题中,您不清楚您是否已将数据集读入data.frame或matrix。所以我假设你在下面的数据集中有一个文本文件:
# read in data
dataset = read.table("dataset.txt", header=T)
# ... or use example data
dataset = read.table(text="ID X Y
1 118 10
2 119 50
3 100 12
4 101 12", header=T, sep=" ")
# create a matrix from columns X & Y and use project as in the question
project(as.matrix(dataset[,c("X","Y")]), "+proj=utm +zone=51 ellps=WGS84")
# [,1] [,2]
# [1,] -48636.65 1109577
# [2,] 213372.05 5546301
# ...
<强>更新强>
评论表明问题来自于将project()
应用于data.frame。 project()
对data.frames无效,因为它会检查is.numeric()
。因此,您需要将数据转换为矩阵,如上例所示。如果您想坚持使用cbind()
的代码,则必须执行以下操作:
X <- dd[,"X"]
Y <- dd[,"Y"]
xy <- cbind(X,Y)
dd["X"]
和dd[,"X"]
之间的区别在于后者不会返回data.frame,因此cbind()
将生成矩阵而不是data.frame。
答案 3 :(得分:1)
基于上面的代码,我还添加了一个区域和半球检测版本(解决了转换问题,如某些评论中所述)+ CRS
字符串的简写以及转换回WSG86:
library(dplyr)
library(sp)
library(rgdal)
library(tibble)
find_UTM_zone <- function(longitude, latitude) {
# Special zones for Svalbard and Norway
if (latitude >= 72.0 && latitude < 84.0 )
if (longitude >= 0.0 && longitude < 9.0)
return(31);
if (longitude >= 9.0 && longitude < 21.0)
return(33)
if (longitude >= 21.0 && longitude < 33.0)
return(35)
if (longitude >= 33.0 && longitude < 42.0)
return(37)
(floor((longitude + 180) / 6) %% 60) + 1
}
find_UTM_hemisphere <- function(latitude) {
ifelse(latitude > 0, "north", "south")
}
# returns a DF containing the UTM values, the zone and the hemisphere
longlat_to_UTM <- function(long, lat, units = 'm') {
df <- data.frame(
id = seq_along(long),
x = long,
y = lat
)
sp::coordinates(df) <- c("x", "y")
hemisphere <- find_UTM_hemisphere(lat)
zone <- find_UTM_zone(long, lat)
sp::proj4string(df) <- sp::CRS("+init=epsg:4326")
CRSstring <- paste0(
"+proj=utm +zone=", zone,
" +ellps=WGS84",
" +", hemisphere,
" +units=", units)
if (dplyr::n_distinct(CRSstring) > 1L)
stop("multiple zone/hemisphere detected")
res <- sp::spTransform(df, sp::CRS(CRSstring[1L])) %>%
tibble::as_data_frame() %>%
dplyr::mutate(
zone = zone,
hemisphere = hemisphere
)
res
}
UTM_to_longlat <- function(utm_df, zone, hemisphere) {
CRSstring <- paste0("+proj=utm +zone=", zone, " +", hemisphere)
utmcoor <- sp::SpatialPoints(utm_df, proj4string = sp::CRS(CRSstring))
longlatcoor <- sp::spTransform(utmcoor, sp::CRS("+init=epsg:4326"))
tibble::as_data_frame(longlatcoor)
}
其中CRS("+init=epsg:4326")
是CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0")
的缩写。
查找UTM区域参考:http://www.igorexchange.com/node/927
答案 4 :(得分:0)
在此示例中,给定坐标的默认UTM区域是50。建议不要将坐标投影到较远的区域中。您可以使用NOAA的NCAT tool检查转换。
下面的代码使用sf
包进行转换。
library(sf)
library(tidyverse)
# Coordinate examples with expected UTM values
coord_sample <- data.frame(
"Northing" = c(1105578.589, 5540547.370),
"Easting" = c(609600.773, 643329.124),
"Latitude" = c(10, 50),
"Longitude" = c(118, 119))
#' Find UTM EPSG code from Latitude and Longitude coordinates (EPSG 4326 WGS84)
#' (vectorised)
#' Source: https://geocompr.robinlovelace.net/reproj-geo-data.html
#' Source: https://gis.stackexchange.com/questions/13291/computing-utm-zone-from-lat-long-point
LatLonToUTMEPSGCode <- function(lat, lon) {
zone_number <- (floor((lon + 180) / 6) %% 60) + 1
# Special zones for Norway
cond_32 <- lat >= 56.0 & lat < 64.0 & lon >= 3.0 & lon < 12.0
zone_number[cond_32] <- 32
# Special zones for Svalbard
cond_lat <- lat >= 72.0 & lat < 84.0
cond_31 <- cond_lat & lon >= 0.0 & lon < 9.0
zone_number[cond_31] <- 31
cond_33 <- cond_lat & lon >= 9.0 & lon < 21.0
zone_number[cond_33] <- 33
cond_35 <- cond_lat & lon >= 21.0 & lon < 33.0
zone_number[cond_35] <- 35
cond_37 <- cond_lat & lon >= 33.0 & lon < 42.0
zone_number[cond_37] <- 37
# EPSG code
utm <- zone_number
utm[lat > 0] <- utm[lat > 0] + 32600
utm[lat <= 0] <- utm[lat <= 0] + 32700
return(utm)
}
sf_sample <- sf::st_as_sf(coord_sample, coords = c("Longitude", "Latitude"),
crs = 4326)
sf_sample %>%
do(cbind(., st_coordinates(.))) %>%
mutate(EPSG = LatLonToUTMEPSGCode(lat = Y, lon = X)) %>%
group_by(EPSG) %>%
do(cbind(as.data.frame(.) %>% select(Northing, Easting),
st_coordinates(st_transform(., crs = head(.$EPSG, 1))))) %>%
ungroup()
您可以通过与预期值进行比较来检查转换:
# A tibble: 2 x 5
EPSG Northing Easting X Y
<dbl> <dbl> <dbl> <dbl> <dbl>
1 32650 1105579 609601 609601 1105579
2 32650 5540547 643329 643329 5540547