Context
这些问题与从PROJ4升级到PROJ6所引起的更改及其对各种R空间包(sp
,sf
,raster
)的影响有关。
我们现在收到了很多关于“已放弃基准”的警告,看起来有点令人担忧,我有点困惑我应该做什么。我可以看到这可能会在某些情况下产生可怕的后果,并且在其他情况下可以忽略它们。
看来我不是唯一一个有点迷失的人(请参见此处)。我希望我的问题和具有特定可再现示例的实例将帮助我们更好地理解这个主题。
我理解我们可以消除警告,并且我已经阅读了上下文: r-spatial博客文章、 升级到PROJ6/GDAL3 和这些研讨会笔记(mapview似乎以不同的方式处理此问题在最近的版本中)。
Questions
问题1:
可能是一个天真的问题:
我理解需要一种新的符号/格式(WKT)在PROJ6中实现(例如由于需要更高的精度),但我不明白为什么需要将旧proj4字符串符号中的基准部分删除。为什么不保持它一直如此(并在新的WKT格式/符号中实现新功能)?
问题2:
似乎我们有3种情况涉及旧proj4格式中的基准删除:
- 没有警告:基准与旧proj4string符号相同(
sf
默认值?) - 我们收到了一个警告“已放弃基准(…),但保留了+ towgs84 =值”
- 我们收到了一个警告“已放弃基准(…)”(在这种情况下,“+towgs84 =”字符串的一部分被丢弃/删除->
sp
默认值?)
下面的示例说明了我们有这些警告的不同情况。
为什么在相同的CRS(这里是EPSG 31370)上有这3种不同的情况?
删除基准和/或+towgs84
部分的后果是什么?
第二个警告比第三个警告更少使我担心吗?
问题3:
在下面的可再现示例中,我尝试从栅格提取与3个点对应的值,栅格和点具有不同的CRS。然而,根据所使用的方法不同,我会得到不同的结果。我有一种印象,这与这个PROJ4 -> PROJ6更改和基准删除有关,但我可能错了。我创建
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.2, PROJ 6.2.1
library(sp)
library(raster)
# create 3 points
coo <- data.frame(x = c(246000, 247000, 246500), y = c(184000, 186000, 185000))
# create an sf spatial object
SF <- st_as_sf(coo, coords = c("x", "y"), crs = 31370)
# Check the CRS :
# the proj4string includes the datum/+towgs84 information - no warning
st_crs(SF)$proj4string
#> [1] "+proj=lcc +lat_0=90 +lon_0=4.36748666666667 +lat_1=51.1666672333333 +lat_2=49.8333339 +x_0=150000.013 +y_0=5400088.438 +ellps=intl +towgs84=-99.059,53.322,-112.486,0.419,-0.83,1.885,-1 +units=m +no_defs"
# Same value with `raster::crs` but with a
# Warning "Discarded datum (...) but +towgs84= values preserved"
raster::crs(SF)
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO"): Discarded datum Unknown_based_on_International_1909_Hayford_ellipsoid in CRS definition,
#> but +towgs84= values preserved
#> CRS arguments:
#> +proj=lcc +lat_0=90 +lon_0=4.36748666666667 +lat_1=51.1666672333333
#> +lat_2=49.8333339 +x_0=150000.013 +y_0=5400088.438 +ellps=intl
#> +towgs84=-99.059,53.322,-112.486,0.419,-0.83,1.885,-1 +units=m +no_defs
# WKT
st_crs(SF)
#> Coordinate Reference System:
#> User input: EPSG:31370
#> wkt:
#> BOUNDCRS[
#> SOURCECRS[
#> PROJCRS["Belge 1972 / Belgian Lambert 72",
#> BASEGEOGCRS["Belge 1972",
#> DATUM["Reseau National Belge 1972",
#> ELLIPSOID["International 1924",6378388,297,
#> LENGTHUNIT["metre",1]]],
#> PRIMEM["Greenwich",0,
#> ANGLEUNIT["degree",0.0174532925199433]],
#> ID["EPSG",4313]],
#> CONVERSION["Belgian Lambert 72",
#> METHOD["Lambert Conic Conformal (2SP)",
#>
#> (...)
#>
#> ID["EPSG",1609],
#> REMARK["Scale difference is given by information source as 0.999999. Given in this record in ppm to assist application usage. Very similar parameter values (to slightly less precision) used for BD72 to ETRS89: see code 1652."]]]
cat(raster::wkt(SF)) # does not work with sf
#> Error in raster::wkt(SF): tentative d'obtenir le slot "crs" d'un objet (classe "sf") qui n'est pas un objet S4
SP点空间对象
简要说,CRS主要以proj4字符串格式存储,并且不像sf
那样保留数据和towgs84
部分。新的WKT符号被存储为CRS对象中的注释,但与sf
不同。
SP <- coo
coordinates(SP) <- ~x+y
proj4string(SP) <- CRS("+init=epsg:31370")
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO"): Discarded
#> datum Reseau_National_Belge_1972 in CRS definition
# the proj4 string do not contain the `towgs84` part
# Warning "Discarded datum (...)"
CRS("+init=epsg:31370")
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO"): Discarded
#> datum Reseau_National_Belge_1972 in CRS definition
#> CRS arguments:
#> +proj=lcc +lat_0=90 +lon_0=4.36748666666667 +lat_1=51.1666672333333
#> +lat_2=49.8333339 +x_0=150000.013 +y_0=5400088.438 +ellps=intl +units=m
#> +no_defs
# With `raster::crs` same proj4string but no warning
raster::crs(SP)
#> CRS arguments:
#> +proj=lcc +lat_0=90 +lon_0=4.36748666666667 +lat_1=51.1666672333333
#> +lat_2=49.8333339 +x_0=150000.013 +y_0=5400088.438 +ellps=intl +units=m
#> +no_defs
# WKT notation + a warning: this WKT is indeed different from the SF one (no datum here ?)
cat(comment(CRS("+init=epsg:31370")))
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO"): Discarded
#> datum Reseau_National_Belge_1972 in CRS definition
#> PROJCRS["Belge 1972 / Belgian Lambert 72",
#> BASEGEOGCRS["Belge 1972",
#> DATUM["Reseau National Belge 1972",
#> ELLIPSOID["International 1924",6378388,297,
#> LENGTHUNIT["metre",1]]],
#>
#> (...)
#>
#> USAGE[
#> SCOPE["unknown"],
#> AREA["Belgium - onshore"],
#> BBOX[49.5,2.5,51.51,6.4]]]
# Same output without warning
cat(raster::wkt(SP))
#> PROJCRS["Belge 1972 / Belgian Lambert 72",
#> BASEGEOGCRS["Belge 1972",
#> DATUM["Reseau National Belge 1972",
#> ELLIPSOID["International 1924",6378388,297,
#> LENGTHUNIT["metre",1]]],
#>
#> (...)
#>
#> USAGE[
#> SCOPE["unknown"],
#> AREA["Belgium - onshore"],
#> BBOX[49.5,2.5,51.51,6.4]]]
栅格
在栅格
中,既存的proj4表示法和新的WKT表示法似乎都被存储了。
r <- raster::raster(system.file("external/test.grd", package="raster"))
raster::crs(r)
#> CRS arguments:
#> +proj=sterea +lat_0=52.1561605555556 +lon_0=5.38763888888889
#> +k=0.9999079 +x_0=155000 +y_0=463000 +datum=WGS84 +units=m +no_defs
cat(raster::wkt(r))
#> PROJCRS["unknown",
#> BASEGEOGCRS["unknown",
#> DATUM["World Geodetic System 1984",
#> ELLIPSOID["WGS 84",6378137,298.257223563,
#> LENGTHUNIT["metre",1]],
#> ID["EPSG",6326]],
#>
#> (...)
#>
#> AXIS["(N)",north,
#> ORDER[2],
#> LENGTHUNIT["metre",1,
#> ID["EPSG",9001]]]]
这个数据集的proj4string部分中不包含+towgs84
部分。但是当您读取具有proj4string中+towgs84
部分的栅格时,似乎会被删除。
无法重现的示例:
GISfolder <- "/my/path"
tmp <- raster(paste0(GISfolder, 'my_file.tif'))
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO"): Discarded
#> datum Unknown_based_on_International_1909_Hayford_ellipsoid in CRS definition
raster::crs(tmp)
#> CRS arguments:
#> +proj=lcc +lat_0=90 +lon_0=4.36748666666667 +lat_1=49.8333339
#> +lat_2=51.1666672333333 +x_0=150000.01256 +y_0=5400088.4378 +ellps=intl
#> +units=m +no_defs
cat(raster::wkt(tmp))
#> PROJCRS["unknown",
#> BASEGEOGCRS["unknown",
#> DATUM["Unknown based on International 1909 (Hayford) ellipsoid",
#> ELLIPSOID["International 1909 (Hayford)",6378388,297,
#> LENGTHUNIT["metre",1,
#> ID["EPSG",9001]]]],
#> PRIMEM["Greenwich",0,
#> ANGLEUNIT["degree",0.0174532925199433],
#> ID["EPSG",8901]]],
#>
#> (...)
#>
#> AXIS["(N)",north,
#> ORDER[2],
#> LENGTHUNIT["metre",1,
#> ID["EPSG",9001]]]]
我应该还需要探索使用stars
包而不是raster
时会发生什么,但这个问题已经很长了(而且我已经有很多基于raster包的代码)
从栅格中提取值
使用raster::extract
的自动投影
# extract the values from the raster,
# the function extract reprojects the points
# in the same crs as the raster layer
extract(r, SF)
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO"): Discarded datum Unknown_based_on_International_1909_Hayford_ellipsoid in CRS definition,
#> but +towgs84= values preserved
#> Warning in .local(x, y, ...): Transforming SpatialPoints to the CRS of the
#> Raster
#> [1] 351.7868 236.4216 309.0073
extract(r, SP)
#> Warning in .local(x, y, ...): Transforming SpatialPoints to the CRS of the
#> Raster
#> [1] 351.7868 236.4216 309.0073
手动将点重新投影到栅格数据的坐标参考系统
使用栅格数据的proj4string进行投影。SF_proj <- st_transform(SF, crs = raster::crs(r))
extract(r, SF_proj)
#> [1] 351.7868 236.4216 309.0073
使用WKT从栅格中提取SF。SF_proj <- st_transform(SF, crs = raster::wkt(r))
extract(r, SF_proj)
#> [1] 351.7868 236.4216 309.0073
从栅格中获取带有proj4string的SP对象。SP_proj <- spTransform(SP, raster::crs(r))
extract(r, SP_proj)
#> [1] 351.7868 236.4216 309.0073
在栅格图像中使用WKT格式的空间参考信息,但是sp::spTransform
不支持该格式,因此无法使用。
# error
SP_proj <- spTransform(SP, raster::wkt(r))
#> Error in CRS(CRSobj): PROJ4 argument-value pairs must begin with +: PROJCRS["unknown",
#> BASEGEOGCRS["unknown",
#> DATUM["World Geodetic System 1984",
#> ELLIPSOID["WGS 84",6378137,298.257223563,
#> LENGTHUNIT["metre",1]],
#> ID["EPSG",6326]],
#>
#> (...)
#>
#> AXIS["(N)",north,
#> ORDER[2],
#> LENGTHUNIT["metre",1,
#> ID["EPSG",9001]]]]
# extract(r, SP_proj)
手动将栅格转换到点的坐标参考系统
使用SF的proj4string(带有数据),->结果与之前的尝试不同
# EPSG 31370 proj4 string with the datum:
lambert72 <- sf::st_crs(31370)$proj4string
lambert72
#> [1] "+proj=lcc +lat_0=90 +lon_0=4.36748666666667 +lat_1=51.1666672333333 +lat_2=49.8333339 +x_0=150000.013 +y_0=5400088.438 +ellps=intl +towgs84=-99.059,53.322,-112.486,0.419,-0.83,1.885,-1 +units=m +no_defs"
# there is a warning when we project the raster but the full string seems to be used
r2 <- raster::projectRaster(r, crs = lambert72)
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO"): Discarded datum Unknown_based_on_International_1909_Hayford_ellipsoid in CRS definition,
#> but +towgs84= values preserved
raster::crs(r2)
#> CRS arguments:
#> +proj=lcc +lat_0=90 +lon_0=4.36748666666667 +lat_1=51.1666672333333
#> +lat_2=49.8333339 +x_0=150000.013 +y_0=5400088.438 +ellps=intl
#> +towgs84=-99.059,53.322,-112.486,0.419,-0.83,1.885,-1 +units=m +no_defs
extract(r2, SP)
#> [1] 341.6399 222.1028 301.2286
使用SF的WKT格式不起作用,因为raster::projectRaster不接受WKT格式作为其crs参数。lambert72 <- sf::st_crs(31370)
lambert72
#> Coordinate Reference System:
#> User input: EPSG:31370
#> wkt:
#> BOUNDCRS[
#> SOURCECRS[
#> PROJCRS["Belge 1972 / Belgian Lambert 72",
#> BASEGEOGCRS["Belge 1972",
#> DATUM["Reseau National Belge 1972",
#> ELLIPSOID["International 1924",6378388,297,
#> LENGTHUNIT["metre",1]]],
#> PRIMEM["Greenwich",0,
#>
#> (...)
#>
#> AREA["Belgium - onshore"],
#> BBOX[49.5,2.5,51.51,6.4]],
#> ID["EPSG",1609],
#> REMARK["Scale difference is given by information source as 0.999999. Given in this record in ppm to assist application usage. Very similar parameter values (to slightly less precision) used for BD72 to ETRS89: see code 1652."]]]
r2 <- raster::projectRaster(r, crs = lambert72)
#> Error in wkt(projto): tentative d'obtenir le slot "crs" d'un objet (classe "crs") qui n'est pas un objet S4
使用SP的proj4string(不带数据)会导致与之前尝试的结果不同。# EPSG 31370 proj4 string without the datum:
lambert72 <- sp::CRS("+init=epsg:31370")@projargs
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO"): Discarded
#> datum Reseau_National_Belge_1972 in CRS definition
lambert72
#> [1] "+proj=lcc +lat_0=90 +lon_0=4.36748666666667 +lat_1=51.1666672333333 +lat_2=49.8333339 +x_0=150000.013 +y_0=5400088.438 +ellps=intl +units=m +no_defs"
# warning
r3 <- raster::projectRaster(r, crs = lambert72)
#> Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO"): Discarded
#> datum Unknown_based_on_International_1909_Hayford_ellipsoid in CRS definition
raster::crs(r3)
#> CRS arguments:
#> +proj=lcc +lat_0=90 +lon_0=4.36748666666667 +lat_1=51.1666672333333
#> +lat_2=49.8333339 +x_0=150000.013 +y_0=5400088.438 +ellps=intl +units=m
#> +no_defs
extract(r3, coo)
#> [1] 348.5775 329.1199 277.2260
会话信息
sessionInfo()
#> R version 3.6.2 (2019-12-12)
#> Platform: x86_64-pc-linux-gnu (64-bit)
#> Running under: Ubuntu 18.04.4 LTS
#>
#> (...)
#>
#> other attached packages:
#> [1] raster_3.3-13 sp_1.4-2 sf_0.9-5 knitr_1.29
#>
#> (...)
#>
用于:
GEOS 3.8.0, GDAL 3.0.2, PROJ 6.2.1
由reprex包(v0.3.0)于2020年09月03日创建
raster::projectRaster
函数,无论您提供的crs格式是什么(作为CRS sp对象或当然作为proj4字符串),它都无法正确投影栅格。我尝试在单独的答案中澄清每个选项的工作原理或失败原因(如果我错了,请纠正我)。 - Gilles San Martin