How to re-project a raster in r - 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))

Related

How to extract data point for a xy coordiante from raster without projected lat lopn coordinates

Hi am trying to extract values for xy point from a sample raster stack ras_dt. The ras_dt is EQUATES data with gridded coordinates within the domain of -115.00,38.00,-110.05,45.00. How can I change the projection and the lat lon coordinates of this raster stack so that I can extract data for point xy as in the code below.
library(raster)
dturl<- "https://www.dropbox.com/s/ztxqpszjfjhpavz/EQUATES_ACONC_O3_SAM.nc?dl=1"
download.file(dturl, "EQUATES_ACONC_O3_SAM.nc")
ras_dt <- raster::stack("EQUATES_ACONC_O3_SAM.nc",varname = "O3")
ras_dt
# the data domain is -115.00,38.00,-110.05,45.00
plot(ras_dt)
xy <- data.frame(lon=-113.0,lat=40.0)
coordinates(xy) <- ~lon + lat
extr_dt <- raster::extract(ras_dt, xy) # how to get O3 values for xy here?
extr_dt
The ras_dt is in "lambertConformalProjection" with following info:
char LambertConformalProjection;
:grid_mapping_name = "lambert_conformal_conic";
:latitude_of_projection_origin = 40.0; // double
:longitude_of_central_meridian = -97.0; // double
:standard_parallel = 33.0, 45.0; // double
:earth_radius = 6370000.0; // double
:_CoordinateTransformType = "Projection";
:_CoordinateAxes = "x y";
You need to set the extent and the coordinate reference system (CRS). Then transform your lon/lat points to that CRS and use extract. From your edited question we now have the CRS.
You specify the "domain", but you need to coordinates in the actual CRS. I do not know what these are, so I will guestimate it, but it will not be correct.
The data
library(terra)
dturl<- "https://www.dropbox.com/s/ztxqpszjfjhpavz/EQUATES_ACONC_O3_SAM.nc?dl=1"
download.file(dturl, "EQUATES_ACONC_O3_SAM.nc", mode="wb")
ras_dt <- rast("EQUATES_ACONC_O3_SAM.nc", "O3")
pcrs <- "+proj=lcc +lon_0=-97 +lat_0=40 +lat_1=33 +lat_2=45 +r =6370000.0"
Rough estimate of the extent:
v <- vect(rbind(c(-115, 38), c(-115, 45), c(-110.05, 38), c(-110.05, 45)), crs="+proj=longlat")
p <- project(v, pcrs)
e <- crds(p) |> apply(2, range) |> as.vector()
e
#[1] -1562368.5 -1025418.3 -139104.3 693662.9
Set the extent and the crs
ext(ras_dt) <- e
crs(ras_dt) <- pcrs
Transform the points to the crs of the raster
xy <- vect(cbind(lon=-113.0,lat=40.0), crs="+proj=longlat")
pxy <- project(xy, pcrs)
And extract
extract(ras_dt, pxy)
# ID O3_LAY=1_TSTEP=1 O3_LAY=1_TSTEP=2
#1 1 41.88482 40.99662
So our raster now looks like this. The spatial resolution should probably be a round number (12,000?)
ras_dt
#class : SpatRaster
#dimensions : 70, 45, 2 (nrow, ncol, nlyr)
#resolution : 11932.23, 11896.67 (x, y)
#extent : -1562369, -1025418, -139104.3, 693662.9 (xmin, xmax, ymin, ymax)
#coord. ref. : +proj=lcc +lat_0=40 +lon_0=-97 +lat_1=33 +lat_2=45 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs
#source : EQUATES_ACONC_O3_SAM.nc:O3
#varname : O3 (O3 )
#names : O3_LAY=1_TSTEP=1, O3_LAY=1_TSTEP=2
#unit : ppbV , ppbV
Can you find and provide the correct extent somewhere in the documentation? And perhaps ask the data providers to follow the NetCDF conventions such that all the metadata required to use the data is stored in the files.

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))

create random points and extract information from a raster

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)

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

Extract raster value based on list of coordinates - spTransform?

I wish to extract raster values based on a list of coordinates. I’ve found online some scripts that include coordinates(), SpatialPoints(), crs() and spTransform() and other that don’t. Could someone kindly explain if script 1 or script 2 is correct and why? Thank you very much!
SCRIPT 1
sites <- read.csv("df.csv")
coordinates(sites)= ~ Longitude+ Latitude
mypoints = SpatialPoints(sites,proj4string = CRS("+init=epsg:4326"))
myproj = CRS(myraster)
points.proj = spTransform(mypoints, myproj)
myvalues = extract(myraster, points.proj)
SCRIPT 2
sites <- read.csv("df.csv")
myvalues = extract(myraster, cbind(sites$Longitude, y=sites$Latitude), df=TRUE, method='simple', cellnumbers=T)
Either could be correct. With RasterLayer r and data.frame sites you can do
v <- extract(r, sites[, c("Longitude", "Latitude")])
Under the assumption that "Longitude" and "Latitude" are variables in sites.
However that only works when r also has a ("Longitude", "Latitude") coordinate reference system. That may not be the case. Consider this RasterLayer
f <- system.file("external/test.grd", package="raster")
r <- raster(f)
r
#class : RasterLayer
#dimensions : 115, 80, 9200 (nrow, ncol, ncell)
#resolution : 40, 40 (x, y)
#extent : 178400, 181600, 329400, 334000 (xmin, xmax, ymin, ymax)
#crs : +proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +units=m +towgs84=565.237,50.0087,465.658,-0.406857,0.350733,-1.87035,4.0812 +no_defs
#source : C:/soft/R/R-3.6.1/library/raster/external/test.grd
#names : test
#values : 128.434, 1805.78 (min, max)
The crs is "sterea ..." and the extent "178400, 181600, ...) shows that the coordinates are clearly not longitude and latitude (they are expressed in meters away from the origin of the crs.)
In this case, you might have a point in the area covered by r
site <- data.frame(Longitude=5.745039, Latitude=50.96254)
But extract returns NA because the crs do not match
extract(r, site)
# [,1]
#[1,] NA
So we do
pts <- SpatialPoints(site)
crs(pts) <- "+proj=longlat +datum=WGS84"
rcrs <- crs(r)
ptrans <- spTransform(pts, rcrs)
And now it works
extract(r, ptrans)
#1529.66

Resources