create random points and extract information from a raster - r

I need to create random points inside a polygon and then extract the information related to the point from a raster.
But I have an error with the function extract(). I try to transform the random points file to a SpatialPoints, but when I try this I have the same error:
Error in (function (classes, fdef, mtable):
unable to find an inherited method for function ‘extract’ for signature ‘"RasterLayer", "sfc_POINT"’
my skript is:
map <- raster("/home.../mosaic.tif")
#class : RasterLayer
#dimensions : 30734, 52746, 1621095564 (nrow, ncol, ncell)
#resolution : 1, 1 (x, y)
#extent : 367836.4, 420582.4, 5805983, 5836717 (xmin, xmax, ymin, ymax)
#crs : +proj=utm +zone=33 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
#source : /home/.../mosaic.tif
#names : mosaic
#values : 0, 65535 (min, max)
#EPSG:32632
pol <- st_read("/home/.../polygon_without_buldings.shp")
#Reading layer `polygon_without_buldings_tegel' from data source `/home/.../polygon_without_buldings_tegel.shp' using driver `ESRI Shapefile'
#Simple feature collection with 4 features and 2 fields
#geometry type: MULTIPOLYGON
#dimension: XY
#bbox: xmin: 383943.5 ymin: 5827189 xmax: 384882.8 ymax: 5828116
#CRS: 32633
#transform the polygon to map's crs EPSG:32632
pol <- st_transform(pol, crs = 32632)
#Simple feature collection with 4 features and 2 fields
#geometry type: MULTIPOLYGON
#dimension: XY
#bbox: xmin: 790333.1 ymin: 5834483 xmax: 791275.4 ymax: 5835389
#CRS: EPSG:32632
#id id_2 geometry
#1 1000 NA MULTIPOLYGON (((790333.1 58...
#2 1 NA MULTIPOLYGON (((790528.6 58...#
rp <- st_sample(pol, size =100, type='random')
#Geometry set for 100 features
#geometry type: POINT
#dimension: XY
#bbox: xmin: 790397.7 ymin: 5834492 xmax: 791188.3 ymax: 5835357
#CRS: EPSG:32632
#First 5 geometries:
rp_sp<-SpatialPoints(rp, proj4string=CRS(map#crs))
buffer <- extract(map, rp, buffer=10.5, fun=mean)
#Error in (function (classes, fdef, mtable) :
#unable to find an inherited method for function ‘extract’ for signature ‘"RasterLayer", "sfc_POINT"’
Maybe is some basic error, but I'm new with spatial data with R. Thanks in advance for your help.

Here is a minimal, reproducible, self-contained example
library(raster)
library(sf)
p <- shapefile(system.file("external/lux.shp", package="raster"))
s <- as(p, "sf")
r <- raster(p, ncol=100, nrow=100)
values(r) <- 1:ncell(r)
There are different solutions, but one thing you can do is this
rp <- st_sample(s, size =100, type='random')
sp <- as(s, "Spatial")
buffer <- extract(r, sp, buffer=0.1, fun=mean)

Related

How to re-project a raster in r

I'm working with a raster layer that looks like this:
class : RasterLayer
dimensions : 7040, 9020, 63500800 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : 0.5, 9020.5, 0.5, 7040.5 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs
source : omi_surface_no2_2005.nc
names : surface_no2_ppb
zvar : surface_no2_ppb
And I need to re-project it so that I can crop it to this shape file:
Simple feature collection with 1 feature and 0 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -80.24869 ymin: 43.05051 xmax: -78.43696 ymax: 44.51657
Geodetic CRS: NAD83
geometry
1 MULTIPOLYGON (((-79.38536 4...
But when I try to re-project it, it doesn't work.
This is the code that I used:
omi_reproj <- projectRaster(omi, crs = crs(gtha_shp))
Has the raster layer been assigned the CRS incorrectly? I'm not sure what I'm doing wrong. If you need the data layers, I can provide a link.
Link to raster: link
This file does not follow the CF conventions for storing raster data.
library(terra)
#terra 1.7.11
x <- rast("omi_surface_no2_2005.nc")
#[1] "vobjtovarid4: **** WARNING **** I was asked to get a varid for dimension named dim1 BUT this dimension HAS NO DIMVAR! Code will probably fail at this point"
#Warning messages:
#1: In min(rs) : no non-missing arguments to min; returning Inf
#2: In min(rs) : no non-missing arguments to min; returning Inf
#3: In max(rs) : no non-missing arguments to max; returning -Inf
#4: [rast] cells are not equally spaced; extent is not defined
You can still read the values with the ncdf4 package and create a SpatRaster "by hand".
Open the ncdf file and inspect its contents
library(ncdf4)
nc <- nc_open("omi_surface_no2_2005.nc")
nc
# 3 variables (excluding dimension variables):
# double surface_no2_ppb[lon_dim,lat_dim] (Chunking: [752,587])
# double LON_CENTER[dim1,latdim] (Chunking: [1,9020])
# double LAT_CENTER[londim,dim1] (Chunking: [7040,1])
Read the relevant data and close the file
lon <- ncdf4::ncvar_get(nc, nc$var[["LON_CENTER"]])
lat <- ncdf4::ncvar_get(nc, nc$var[["LAT_CENTER"]])
d <- ncdf4::ncvar_get(nc, nc$var[["surface_no2_ppb"]])
nc_close(nc)
Create a SpatRaster
library(terra)
x <- rast(t(d[, ncol(d):1]), ext=c(range(lon), range(lat)), crs="+proj=lonlat")
plot(sqrt(x))

apply a function over a list of raster layers

I have a list of 34 RasterLayers like this:
[[34]]
class : RasterLayer
band : 1 (of 10 bands)
dimensions : 6899, 9663, 66665037 (nrow, ncol, ncell)
resolution : 0.0002694946, 0.0002694946 (x, y)
extent : -6.685352, -4.081226, 39.39795, 41.2572 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs
source : D:/TFM/Imagenes/Imagenes_sinClip/2017.tif
names : X2017
I want to crop all the RasterLayers of the list using a simple feature like this:
> aoi
Simple feature collection with 1 feature and 2 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: -6.571744 ymin: 39.44875 xmax: -4.10362 ymax: 41.22031
Geodetic CRS: WGS 84
Id area geometry
1 0 29488.98 POLYGON ((-6.122013 41.2203...
To do that, I used lapply:
crop <- lapply(x = myrasterList, y = aoi, FUN = crop(x, y))
But I get the following error:
Error in h(simpleError(msg, call)) :
error in evaluating the argument 'x' in selecting a method for function 'crop': objeto 'x' no encontrado
The FUN argument of lapply does not work like that when you add arguments to the function. You need to do something like
crop <- lapply(myrasterList, y = aoi, FUN = function(i) crop(i, y))

Unknown CRS in QGIS when projecting to EPSG:25833 in R

I want to project a spatial data frame to EPSG 25833 in R but QGIS does not seem to know it (for reproducibility, I use the code jazzurro created in his/her answer to this question with minor changes)
library(rgdal)
mydf <- structure(list(longitude = c(128.6979, 153.0046, 104.3261, 124.9019,
126.7328, 153.2439, 142.8673, 152.689), latitude = c(-7.4197,
-4.7089, -6.7541, 4.7817, 2.1643, -5.65, 23.3882, -5.571)), .Names = c("longitude",
"latitude"), class = "data.frame", row.names = c(NA, -8L))
### Get long and lat from your data.frame. Make sure that the order is in lon/lat.
xy <- mydf[,c(1,2)]
# Here I use the projection EPSG:25833
spdf <- SpatialPointsDataFrame(coords = xy, data = mydf,
proj4string = CRS("+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"))
#Export as shapefile
writeOGR(spdf, "file location", "proj_test", driver="ESRI Shapefile",overwrite_layer = T) #now I write the subsetted network as a shapefile again
Now when I load the shapefile into QGIS it doesn´t know the projection.
Any ideas?
In making your SpatialPointsDataFrame:
# Wrong!
spdf <- SpatialPointsDataFrame(coords = xy, data = mydf,
proj4string = CRS("+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"))`
You are telling the data frame what crs your points are in, so you should specify 4326 since your original data is lon/lat.
So it should be:
spdf <- SpatialPointsDataFrame(coords = xy, data = mydf,
proj4string = CRS("+proj=longlat +datum=WGS84"))
And then you can transform the data to another CRS using spTransform:
spTransform(spdf, CRS('+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'))
For this particular data, we get an error because one of the points doesn't convert to your target CRS:
Error in spTransform(xSP, CRSobj, ...) : failure in points 3 In
addition: Warning message: In spTransform(xSP, CRSobj, ...) : 1
projected point(s) not finite
I prefer working in sf so we could also do:
library(sf)
sfdf <- st_as_sf(mydf, coords = c('longitude', 'latitude'), crs=4326, remove=F)
sfdf_25833 <- sfdf %>% st_transform(25833)
sfdf_25833
#> Simple feature collection with 8 features and 2 fields (with 1 geometry empty)
#> geometry type: POINT
#> dimension: XY
#> bbox: xmin: 5589731 ymin: -19294970 xmax: 11478870 ymax: 19337710
#> epsg (SRID): 25833
#> proj4string: +proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs
#> longitude latitude geometry
#> 1 128.6979 -7.4197 POINT (10198485 -17980649)
#> 2 153.0046 -4.7089 POINT (5636527 -19294974)
#> 3 104.3261 -6.7541 POINT EMPTY
#> 4 124.9019 4.7817 POINT (11478868 18432292)
#> 5 126.7328 2.1643 POINT (11046583 19337712)
#> 6 153.2439 -5.6500 POINT (5589731 -19158700)
#> 7 142.8673 23.3882 POINT (6353660 16093116)
#> 8 152.6890 -5.5710 POINT (5673080 -19163103)
and you can write and open with QGIS using:
write_sf(sfdf_25833, 'mysf.gpkg')

Zonal operation using an overlapped-ratified raster which comes from two other ratified rasters

I have the following reclassify & ratified rasters that I am trying to intercept/overlay/overlap to get a new one. The idea is to get a new overlayed raster from the interception areas of the rasters R1 and R2. Once done this, I would do zonal operations. Here the R1, R2, ED rasters.
R1:
class : RasterLayer
dimensions : 1399, 1855, 2595145 (nrow, ncol, ncell)
resolution : 0.008333333, 0.008333333 (x, y)
extent : -13.69167, 1.766667, 49.86667, 61.525 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
source : memory
names : UK_GDP_2010_PPP_percapita_km2
values : 1, 6 (min, max)
attributes :
ID AG
from: 1 a
to : 6 f
R2:
class : RasterLayer
dimensions : 1399, 1855, 2595145 (nrow, ncol, ncell)
resolution : 0.008333333, 0.008333333 (x, y)
extent : -13.69167, 1.766667, 49.86667, 61.525 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
source : memory
names : layer
values : 1, 5 (min, max)
attributes :
ID AG
1 A
2 B
3 C
4 D
5 E
Here the code to intercept/overlay/overlap
1st approach
library(sf)
library(tidyverse)
R1_SPDF <- as(R1,'SpatialPolygonsDataFrame')
R1_SPDF <- st_as_sf(R1_SPDF)
R2_SPDF <- as(R2,'SpatialPolygonsDataFrame')
R2_SPDF <- st_as_sf(R2_SPDF)
R3 <- st_intersection(R1_SPDF, R2_SPDF)
R3:
Simple feature collection with 1174501 features and 2 fields
geometry type: POLYGON
dimension: XY
bbox: xmin: -8.166667 ymin: 50.01667 xmax: 1.541667 ymax: 59.55
epsg (SRID): 4326
proj4string: +proj=longlat +datum=WGS84 +no_defs
First 10 features:
UK_GDP_2010_PPP_percapita_km2 layer
1 1 1
2 1 1
2.1 1 1
3 1 1
3.1 1 1
4 1 1
4.1 1 1
1.1 1 1
5 1 1
6 1 1
geometry
1 POLYGON ((-1.641667 59.55, ...
2 POLYGON ((-1.633333 59.55, ...
2.1 POLYGON ((-1.633333 59.55, ...
3 POLYGON ((-1.625 59.55, -1....
3.1 POLYGON ((-1.625 59.55, -1....
4 POLYGON ((-1.616667 59.55, ...
4.1 POLYGON ((-1.616667 59.55, ...
1.1 POLYGON ((-1.641667 59.5416...
5 POLYGON ((-1.65 59.54167, -...
6 POLYGON ((-1.641667 59.5416...
However, I am not sure if this result is what I am looking for, because I expect a new ratified raster R3 with the overlayed areas formed with the combination/interception of R1 and R2 areas (R3 areas ratify: Aa,.. Af,…,Ea,…Ef) or something like that.
Expected R3:
class : RasterLayer
dimensions : #from intersection
resolution : 0.008333333, 0.008333333 (x, y)
extent : -13.69167, 1.766667, 49.86667, 61.525 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
names : layer
values : 1, 30 (min, max) #aproximately 30 because R1: ID=6, and R2: ID=5.
attributes :
ID AGnew
1 Aa
2 Ab
. .
. .
. .
30 Ef
Here a second try using the raster package:
2nd approach
library(raster)
R3.1 <- intersect(R1_SPDF, R2_SPDF)
R3.1:
Simple feature collection with 485611 features and 0 fields
geometry type: POLYGON
dimension: XY
bbox: xmin: -8.65 ymin: 49.875 xmax: 1.766667 ymax: 60.84167
epsg (SRID): 4326
proj4string: +proj=longlat +datum=WGS84 +no_defs
First 10 features:
geometry
1 POLYGON ((-0.9 60.84167, -0...
2 POLYGON ((-0.8916667 60.841...
3 POLYGON ((-0.8833333 60.841...
4 POLYGON ((-0.875 60.84167, ...
5 POLYGON ((-0.85 60.84167, -...
6 POLYGON ((-0.8416667 60.841...
7 POLYGON ((-0.9 60.83333, -0...
8 POLYGON ((-0.8916667 60.833...
9 POLYGON ((-0.8833333 60.833...
10 POLYGON ((-0.875 60.83333, ...
Once I got the R3, I expect to do the following zonal operation. Sum the values of ED raster within the R3 overlayed areas.
sum_R <- zonal(ED, R3, "sum")
Any recommendation is very welcome.
I think the answer in not clear at all, though I also think you already have the answer.
Perhaps your main issue here is that you are working with relative large datasets and you do not manage to see what is going on at every stage.
So for the sake of simplicity I propose a smaller instance of your problem. Notice that when asking in stackoverflow this approach may be more useful to get help. As a matter of fact your files may be too heavey to download and use in some computers, avoiding people to get involved.
But let's go to the code.
library(tidyverse)
library(raster)
library(sf)
library(tmap)
You basically have two rasters with the same resolution, location and extent as the followings:
R1 <- raster(ncol=10, nrow=10, xmn = 0, xmx=10, ymn = 0, ymx = 10)
R2 <- raster(ncol = 10, nrow = 10, xmn = 0, xmx=10, ymn = 0, ymx = 10)
values(R1) <- c(rep(1,ncell(R1)/2), rep(2,ncell(R1)/2))
values(R2) <- rep(10,ncell(R2))
with these kind of files you can perfomer directly many operations. The same extent and resolution is a plus:
Rsum <- R1 + R2
plot(R1) #See the legend of the plot
plot(R2) #See the legend of the plot
plot(Rsum) #See the legend of the plot
I do not see why you need to perform many other operation to get to a zonal operation.
It would make sense if your rasters were different. For example:
R2_Alt <- raster(ncol = 5, nrow = 2, xmn = 0, xmx=10, ymn = 0, ymx = 10) #Alt for alternative
values(R2_Alt) <- rep(10,ncell(R2))
In the case of using R2_Al a simple operation could produce a mistake:
Test <- R2_Alt + R1
So it make sense to move to vector files:
R1_sp <- as(R1, "SpatialPolygonsDataFrame")
R2_Alt_sp <- as(R2_Alt, "SpatialPolygonsDataFrame")
R1_sf <- st_as_sf(R1_sp)
R2_Alt_sf <- st_as_sf(R2_Alt_sp)
names(R1_sf)[1] <- "V1" #Just to get differente variable names
names(R2_Alt_sf)[1] <- "V2_A"
tm_shape(R1_sf) + tm_polygons(border.col = "black") +
tm_shape(R2_Alt_sf) + tm_polygons(border.col = "red", lwd = 4, alpha = 0)
And here is where having a smaller instance of your problem could shed light on your issues:
Int <- st_intersection(R2_Alt_sf, R1_sf)
View(Int)
plot(st_geometry(Int))
You can also see the outcome with the former R2 raster:
R2_sp <- as(R2, "SpatialPolygonsDataFrame")
R2_sf <- st_as_sf(R2_sp)
names(R2_Alt_sf)[1] <- "V2_A"
Int2 <- st_intersection(R2_sf,R1_sf)
Lastly, be sure that the operation you need is intersection. see
This.
I know this answer is not really an answer, but I hope that it helps you to get closer.
Let me know what you think and put here all the feedback.
all the best

Create voronoi polygon with simple feature in R

I'm not sure if I completely understood the help page to create voronoi polygons.
library(sf)
# function to get polygon from boundary box
bbox_polygon <- function(x) {
bb <- sf::st_bbox(x)
p <- matrix(
c(bb["xmin"], bb["ymin"],
bb["xmin"], bb["ymax"],
bb["xmax"], bb["ymax"],
bb["xmax"], bb["ymin"],
bb["xmin"], bb["ymin"]),
ncol = 2, byrow = T
)
sf::st_polygon(list(p))
}
nc <- st_centroid(st_read(system.file("shape/nc.shp", package="sf")))["BIR79"]
box <- st_sfc(bbox_polygon(nc))
v <- st_voronoi(nc, box)
plot(v)
output
Any idea to fix it?
Using the st_voronoi() example from the sf doc pages as a starting point, it seems that st_voronoi() doesn't work with an sf object consisting of points.
library(sf)
# function to get polygon from boundary box
bbox_polygon <- function(x) {
bb <- sf::st_bbox(x)
p <- matrix(
c(bb["xmin"], bb["ymin"],
bb["xmin"], bb["ymax"],
bb["xmax"], bb["ymax"],
bb["xmax"], bb["ymin"],
bb["xmin"], bb["ymin"]),
ncol = 2, byrow = T
)
sf::st_polygon(list(p))
}
nc <- st_read(system.file("shape/nc.shp", package="sf"))["BIR79"]
nc_centroids <- st_centroid(nc)
box <- st_sfc(bbox_polygon(nc_centroids))
head(nc_centroids)
Each point has a separate geometry entry.
Simple feature collection with 6 features and 1 field
geometry type: POINT
dimension: XY
bbox: xmin: -81.49826 ymin: 36.36145 xmax: -76.0275 ymax: 36.49101
epsg (SRID): 4267
proj4string: +proj=longlat +datum=NAD27 +no_defs
BIR79 geometry
1 1364 POINT(-81.4982613405682 36....
2 542 POINT(-81.125145134236 36.4...
3 3616 POINT(-80.6857465738484 36....
4 830 POINT(-76.0275025784544 36....
5 1606 POINT(-77.4105635619488 36....
6 1838 POINT(-76.9947769754215 36....
This combines the points into a multipoint geometry:
head(st_union(nc_centroids))
Output:
Geometry set for 1 feature
geometry type: MULTIPOINT
dimension: XY
bbox: xmin: -84.05976 ymin: 34.07663 xmax: -75.80982 ymax: 36.49101
epsg (SRID): 4267
proj4string: +proj=longlat +datum=NAD27 +no_defs
MULTIPOINT(-84.0597597853139 35.131067104959, -...
Using the union of points instead of the original sf object works:
v <- st_voronoi(st_union(nc_centroids), box)
plot(v, col = 0)
And here's how to get the correct state boundary instead of the original bounding box.
plot(st_intersection(st_cast(v), st_union(nc)), col = 0) # clip to smaller box
plot(nc_centroids, add = TRUE)
I'm trying to do something similar with marked points and I need to preserve the attributes of the points for the resulting tiles. Haven't figured that out yet.

Resources