从R中的空间数据中提取度数、米等测量单位。

6
我想从R中的空间对象中提取度量单位(十进制度、米、英尺等)。例如,如果我有一个使用WGS84坐标参考系统(EPSG:4326)的SF数据框,则希望能够确定坐标是以十进制度为单位指定的。同样,我希望能够确定UTM坐标(例如EPSG:32615)是以米为单位指定的。
我尝试使用sf包中的st_crs()函数来返回以文本格式表示的坐标参考系统。但是,我难以确定从该文本中提取度量单位的正则表达式是否能够可靠地适用于各种坐标系统。
是否有现有的函数返回空间对象的测量单位?
例如,以下代码生成了一个使用WGS84坐标系的SF数据框:
library(sf)
#> Linking to GEOS 3.8.1, GDAL 3.2.1, PROJ 7.2.1

cities <- st_sf(city = "London", geometry = st_sfc(st_point(c(-0.1276, 51.5072))), crs = 4326)

cities
#> Simple feature collection with 1 feature and 1 field
#> Geometry type: POINT
#> Dimension:     XY
#> Bounding box:  xmin: -0.1276 ymin: 51.5072 xmax: -0.1276 ymax: 51.5072
#> Geodetic CRS:  WGS 84
#>     city                geometry
#> 1 London POINT (-0.1276 51.5072)

创建于2021-12-21,使用reprex包 (v2.0.1)

我正在寻找一个函数,可以让我确定数据集的空间单位是十进制度数。例如,如果该函数被称为st_crs_unit(),那么我希望调用st_crs_unit(cities)并返回单位"degrees"或类似的内容。

st_crs()以良好文本格式提供关于CRS的信息,包括坐标系统(CS[])对于两个轴使用"degree"作为ANGLEUNIT,但这个文本的结构在不同的坐标系统中变化很大,因此我不能确定在某些系统上训练的正则表达式将适用于所有系统。

st_crs(cities)
#> Coordinate Reference System:
#>   User input: EPSG:4326 
#>   wkt:
#> GEOGCRS["WGS 84",
#>     DATUM["World Geodetic System 1984",
#>         ELLIPSOID["WGS 84",6378137,298.257223563,
#>             LENGTHUNIT["metre",1]]],
#>     PRIMEM["Greenwich",0,
#>         ANGLEUNIT["degree",0.0174532925199433]],
#>     CS[ellipsoidal,2],
#>         AXIS["geodetic latitude (Lat)",north,
#>             ORDER[1],
#>             ANGLEUNIT["degree",0.0174532925199433]],
#>         AXIS["geodetic longitude (Lon)",east,
#>             ORDER[2],
#>             ANGLEUNIT["degree",0.0174532925199433]],
#>     USAGE[
#>         SCOPE["Horizontal component of 3D system."],
#>         AREA["World."],
#>         BBOX[-90,-180,90,180]],
#>     ID["EPSG",4326]]

这段内容是由reprex包(v2.0.1)在2021-12-21创建的

例如,如果我们将相同的数据转换为使用UTM 30N坐标系,那么st_crs()的输出会发生显著变化。

st_crs(st_transform(cities, crs = 32630))
#> Coordinate Reference System:
#>   User input: EPSG:32630 
#>   wkt:
#> PROJCRS["WGS 84 / UTM zone 30N",
#>     BASEGEOGCRS["WGS 84",
#>         DATUM["World Geodetic System 1984",
#>             ELLIPSOID["WGS 84",6378137,298.257223563,
#>                 LENGTHUNIT["metre",1]]],
#>         PRIMEM["Greenwich",0,
#>             ANGLEUNIT["degree",0.0174532925199433]],
#>         ID["EPSG",4326]],
#>     CONVERSION["UTM zone 30N",
#>         METHOD["Transverse Mercator",
#>             ID["EPSG",9807]],
#>         PARAMETER["Latitude of natural origin",0,
#>             ANGLEUNIT["degree",0.0174532925199433],
#>             ID["EPSG",8801]],
#>         PARAMETER["Longitude of natural origin",-3,
#>             ANGLEUNIT["degree",0.0174532925199433],
#>             ID["EPSG",8802]],
#>         PARAMETER["Scale factor at natural origin",0.9996,
#>             SCALEUNIT["unity",1],
#>             ID["EPSG",8805]],
#>         PARAMETER["False easting",500000,
#>             LENGTHUNIT["metre",1],
#>             ID["EPSG",8806]],
#>         PARAMETER["False northing",0,
#>             LENGTHUNIT["metre",1],
#>             ID["EPSG",8807]]],
#>     CS[Cartesian,2],
#>         AXIS["(E)",east,
#>             ORDER[1],
#>             LENGTHUNIT["metre",1]],
#>         AXIS["(N)",north,
#>             ORDER[2],
#>             LENGTHUNIT["metre",1]],
#>     USAGE[
#>         SCOPE["Engineering survey, topographic mapping."],
#>         AREA["Between 6°W and 0°W, northern hemisphere between equator and 84°N, onshore and offshore. Algeria. Burkina Faso. Côte' Ivoire (Ivory Coast). Faroe Islands - offshore. France. Ghana. Gibraltar. Ireland - offshore Irish Sea. Mali. Mauritania. Morocco. Spain. United Kingdom (UK)."],
#>         BBOX[0,-6,84,0]],
#>     ID["EPSG",32630]]

本文内容由reprex包(v2.0.1)于2021-12-21创建

是否存在一种现有的R函数,可以返回空间对象的测量单位?


1
请附上一些可重现的数据和期望的输出,这样其他人才能帮助您。 - Chris Ruehlemann
通常我会这样做,但在这种情况下,我不知道它如何有帮助(无论是从SF对象中提取测量单位的函数是否存在),而且还可能通过使问题变得更长而使问题不够清晰。话虽如此,如果有帮助,我现在已经添加了一些虚拟代码。 - Matt Ashby
1个回答

8

st_crs()有一个parameters参数,当设置为TRUE时会返回包括CRS单位在内的一些有用的CRS参数列表。以下是使用内置的nc数据的示例:

library(sf)

nc_4267 <- read_sf(system.file("shape/nc.shp", package="sf"))
nc_3857 <- st_transform(nc_4267, 3857)

st_crs(nc_4267, parameters = TRUE)$units_gdal
#> [1] "degree"
st_crs(nc_3857, parameters = TRUE)$units_gdal
#> [1] "metre"

请注意,对于某些目的,st_is_longlat() 可能已经足够了:
st_is_longlat(nc_4267)
#> [1] TRUE
st_is_longlat(nc_3857)
#> [1] FALSE

太好了,谢谢! - Matt Ashby

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接