[英]problem cropping sf object to extent of another sf polygon in R
I often download large-scale climate data and crop it to the extent of some spatial object.我经常下载大规模的气候数据,并将其裁剪到一些空间 object 的范围内。 I have code that still works to do this with sea surface temperature data cropped to fall within a "bathymetric mask" (a shape that falls within a bounding box and is shallower than a certain depth in the oceans).
我的代码仍然可以通过将海面温度数据裁剪为落入“测深掩码”(一种位于边界框内且比海洋中的某个深度浅的形状)来执行此操作。 I downloaded a new temperature dataset from here ("sst.mon.mean.nc") , and I can't figure out how to crop it correctly.
我从这里 ("sst.mon.mean.nc")下载了一个新的温度数据集,但我不知道如何正确裁剪它。 Everything I have tried produces an empty sf object.
我尝试过的所有东西都会产生一个空的 sf object。
Here is code to reproduce the issue having downloaded the dataset linked above:这是下载上面链接的数据集后重现问题的代码:
library(tidyverse)
library(raster)
library(sf)
library(oceanmap)
# set bounding box
latrange <- c(35, 45)
lonrange <- c(-78, -66)
# download COBE data and put in working directory, then run:
cobe.raw <- raster::stack("sst.mon.mean.nc")
cobe.tidy <- raster::as.data.frame(cobe.raw, xy=TRUE) %>%
pivot_longer(cols=c(-x, -y), names_to="date", values_to="sst") %>%
filter(!is.na(sst))
# get bathymetry with bounding box
bathy <- get.bathy(lon = lonrange, lat = latrange, visualize = F, res = 15)
# get CRS for reprojecting COBE
bathy.crs <- bathy %>%
as("SpatialPolygonsDataFrame") %>%
st_as_sf() %>%
st_crs()
# make bathymetry mask
bathy.mask <- bathy %>%
as("SpatialPolygonsDataFrame") %>%
st_as_sf() %>% # retains CRS
dplyr::filter(layer <= 300) # get rid of points over 300 m deep
# also tried making a polygon union
bathy.mask.union <- st_union(bathy.mask)
# make COBE sf object
cobe.sf <- cobe.tidy %>%
mutate(x=x-180) %>% # change lon to -180/+180 from +360
st_as_sf(coords=c("x","y"), crs = bathy.crs)
I tried cobe.sf %>% st_intersect(bathy.mask)
, cobe.sf %>% st_intersect(bathy.mask.union)
, cobe.sf %>% st_filter(bathy.mask)
, and cobe.sf %>% st_join(bathy.mask, left=FALSE)
(which was in the original code and still works for all the other data files).我试过
cobe.sf %>% st_intersect(bathy.mask)
、 cobe.sf %>% st_intersect(bathy.mask.union)
、 cobe.sf %>% st_filter(bathy.mask)
和cobe.sf %>% st_join(bathy.mask, left=FALSE)
(在原始代码中,仍然适用于所有其他数据文件)。 They all produce an empty object, which makes me suspect I am missing something stupid about the raw COBE data.他们都产生了一个空的 object,这让我怀疑我错过了关于原始 COBE 数据的一些愚蠢的东西。 COBE is a very large dataset but I did plot
cobe.sf
and it has a global extent and looks like a normal map. COBE 是一个非常大的数据集,但我做了 plot
cobe.sf
,它具有全局范围,看起来像普通的 map。 Any ideas?有任何想法吗? Here is the summary of each object:
以下是每个 object 的摘要:
> cobe.sf
Simple feature collection with 67932249 features and 2 fields
geometry type: POINT
dimension: XY
bbox: xmin: -179.5 ymin: -84.5 xmax: 179.5 ymax: 89.5
epsg (SRID): 4326
proj4string: +proj=longlat +ellps=WGS84 +no_defs
# A tibble: 67,932,249 x 3
date sst geometry
<chr> <dbl> <POINT [°]>
1 X1891.01.01 -1.80 (-179.5 89.5)
2 X1891.02.01 -1.80 (-179.5 89.5)
3 X1891.03.01 -1.80 (-179.5 89.5)
4 X1891.04.01 -1.80 (-179.5 89.5)
5 X1891.05.01 -1.80 (-179.5 89.5)
6 X1891.06.01 -1.80 (-179.5 89.5)
7 X1891.07.01 -1.80 (-179.5 89.5)
8 X1891.08.01 -1.80 (-179.5 89.5)
9 X1891.09.01 -1.80 (-179.5 89.5)
10 X1891.10.01 -1.80 (-179.5 89.5)
# ... with 67,932,239 more rows
> bathy.mask
Simple feature collection with 497 features and 1 field
geometry type: POLYGON
dimension: XY
bbox: xmin: -78 ymin: 35 xmax: -66 ymax: 45
epsg (SRID): 4326
proj4string: +proj=longlat +ellps=WGS84 +no_defs
First 10 features:
layer geometry
1 5 POLYGON ((-67.25 45, -67 45...
2 44 POLYGON ((-67 45, -66.75 45...
3 127 POLYGON ((-66.75 45, -66.5 ...
4 122 POLYGON ((-66.5 45, -66.25 ...
5 95 POLYGON ((-66.25 45, -66 45...
6 5 POLYGON ((-67.75 44.75, -67...
7 47 POLYGON ((-67.5 44.75, -67....
8 77 POLYGON ((-67.25 44.75, -67...
9 50 POLYGON ((-67 44.75, -66.75...
10 159 POLYGON ((-66.75 44.75, -66...
> bathy.mask.union
Geometry set for 1 feature
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -78 ymin: 35 xmax: -66 ymax: 45
epsg (SRID): 4326
proj4string: +proj=longlat +ellps=WGS84 +no_defs
MULTIPOLYGON (((-75.5 39.5, -75.25 39.5, -75.25...
Your conversion from 0-360 longitude to -180-180 longitude was off.您从 0-360 经度到 -180-180 经度的转换已关闭。 See here for example: https://gis.stackexchange.com/questions/201789/verifying-formula-that-will-convert-longitude-0-360-to-180-to-180
例如,请参见此处: https://gis.stackexchange.com/questions/201789/verifying-formula-that-will-convert-longitude-0-360-to-180-to-180
Data: Note that I sampled 10,000 rows.数据:请注意,我抽样了 10,000 行。
# cobe.tidy
set.seed(123)
cobe.tidy <- raster::as.data.frame(cobe.raw, xy=TRUE) %>%
pivot_longer(cols=c(-x, -y), names_to="date", values_to="sst") %>%
filter(!is.na(sst))
cobe.sample <- cobe.tidy %>%
sample_n(10000)
Original version: cobe
gets projected incorrectly and your bathymetry ends up in China/Mongolia (or rather, China/Mongolia end up in New England).原始版本:
cobe
投影不正确,您的测深仪最终出现在中国/蒙古(或者更确切地说,中国/蒙古最终出现在新英格兰)。
# make COBE sf object
cobe.sf <- cobe.sample %>%
mutate(x=x-180) %>% # change lon to -180/+180 from +360
st_as_sf(coords=c("x","y"), crs = bathy.crs)
ggplot() +
geom_sf(data = cobe.sf) +
geom_sf(data = bathy.mask.union, fill = "red")
New version: Bathymetry correctly appears off of New England.新版本:测深仪正确出现在新英格兰附近。
# make COBE sf object
cobe.sf <- cobe.sample %>%
mutate(x= ifelse(x >= 180, x-360, x)) %>% # change lon to -180/+180 from +360
st_as_sf(coords=c("x","y"), crs = bathy.crs)
ggplot() +
geom_sf(data = cobe.sf) +
geom_sf(data = bathy.mask.union, fill = "red")
To clip, we use st_intersection()
.要剪辑,我们使用
st_intersection()
。 In this case, you could also do cobe.sf[bathy.mask.union,]
.在这种情况下,您也可以执行
cobe.sf[bathy.mask.union,]
。
output <- cobe.sf %>%
st_intersection(bathy.mask)
ggplot() +
geom_sf(data = output) +
geom_sf(data = bathy.mask.union, fill = "red", alpha = 0.5)
output
Simple feature collection with 10 features and 2 fields
geometry type: POINT
dimension: XY
bbox: xmin: -77.5 ymin: 36.5 xmax: -67.5 ymax: 43.5
CRS: +proj=longlat +ellps=WGS84
# A tibble: 10 x 3
date sst geometry
<chr> <dbl> <POINT [°]>
1 X1992.11.01 8.42 (-77.5 43.5)
2 X1896.10.01 15.4 (-67.5 40.5)
3 X1913.09.01 19.1 (-70.5 40.5)
4 X1911.01.01 8.03 (-67.5 40.5)
5 X1932.12.01 7.34 (-69.5 42.5)
6 X1928.03.01 2.67 (-70.5 42.5)
7 X1974.07.01 20.4 (-73.5 40.5)
8 X2013.02.01 4.32 (-67.5 43.5)
9 X1899.11.01 11.4 (-71.5 41.5)
10 X1941.06.01 22.1 (-75.5 36.5)
Seems like what you need to do is似乎你需要做的是
cobe.raw <- raster::stack("sst.mon.mean.nc")
cobe.rawr <- rotate(cobe.raw)
And take it from there从那里拿走
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.