これを行う方法のかなり単純な例を見つけましたが、うまく機能しません。私は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
しかし、これは例の数です。何千もの座標を変換する必要があり、それらをテーブルからこのスクリプトに取得する方法がわかりません
データセットには、ID、X、Yの3つの列があります。この方程式を使用してそれらを変換するにはどうすればよいですか?私はこれに何週間も行き詰まっています
座標に関連付けられているすべてのステップで適切な投影メタデータが確実に得られるように、できるだけ早くポイントをSpatialPointsDataFrame
オブジェクトに変換することをお勧めします。
見る ?"SpatialPointsDataFrame-class"
は、単純なdata.framesまたはマトリックスをSpatialPointsDataFrameオブジェクトに変換する方法の詳細です。
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
緯度と経度のポイントを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)
あなたの質問では、データセットをdata.frameまたはマトリックスにすでに読み込んでいるかどうかは不明です。したがって、以下では、テキストファイルにデータセットがあると仮定します。
_# 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()
はis.numeric()
をチェックするため、data.framesでは機能しません。したがって、上記の例のように、データを行列に変換する必要があります。 cbind()
を使用するコードを使い続けたい場合は、次のことを行う必要があります。
_ X <- dd[,"X"]
Y <- dd[,"Y"]
xy <- cbind(X,Y)
_
_dd["X"]
_と_dd[,"X"]
_の違いは、後者はdata.frameを返さず、結果としてcbind()
はdata.frameではなく行列を生成することです。
上記のコードに基づいて、(一部のコメントで説明されているように、変換の問題を解決する)ゾーンと半球の検出のバージョンと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
この例では、特定の座標のデフォルトのUTMゾーンは50です。座標を遠くのゾーンに投影することはお勧めしません。 NOAAの NCATツール を使用して変換を確認できます。
以下のコードは、変換を行うために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