I'm tring to extract pixels values from raster by intersct with SPDF (SpatialPolygonsDataFrame), but gives an error:
library(rgeos)
library(raster)
I have to do the same with some other rasters and SPDF similar to those in the summaries below:
My SPDF:
rings<-readOGR("SPDF.shp")
sumarry(SPDF)
Object of class SpatialPolygonsDataFrame
Coordinates:
min max
x -73.99045 -44.241589
y -18.04159 5.271841
Is projected: FALSE
proj4string : [ +proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs]
Data attributes:
Hectares
Min. : 52
1st Qu.: 31110
Median : 141736
Mean : 442267
3rd Qu.: 531011
Max. :4203563
My raster data :
ras_PI<-raster("ras_PI.tif")
ras_PI
class : RasterLayer
dimensions : 86662, 111765, 9685778430 (nrow, ncol, ncell)
resolution : 0.0002689995, 0.0002690002 (x, y)
extent : -73.97832, -43.91358, -18.04061, 5.271491 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs
source : C:/Users/kleds/OneDrive/Documentos/mestrado/PRODES_APs/pAP_PI.tif
names : pAP_PI
values : 0, 1 (min, max)
Here begins my code:
dirs<-"~/prodes/PRODES_APs"
work_dirs<-"~/prodes/PRODES_APs"
#Create a for to define the rasters directory, and to be used in the subsequent for
for (m in 1:length(dirs)) {
files<-file.path(dirs[m],list.files(path = dirs[m], pattern = ".tif"))
nomes <- list.files(path = dirs[m], pattern = ".tif")
nomes <- substr(nomes,1,nchar(nomes)-4)
}
#create a for to call simultaneously raster layer of interest, and each SPDF (initial polygons, rings and control)
#vectors to use in the for
AP<-c("PI","TI","UN","US")
AW <- c("arc","wood")
km<-c("min","1km_","2km_","3km_","4km_","5km_","6km_","7km_","8km_","9km_",10km_,"10km","20km","30km","40km","50km","60km","70km", "controle")
#empty Data Frame to save my results
results<-data.frame()
for (a in 1:(min(length(files), length(AP)))){
setwd(work_dirs)
r<-files[a]
i<- AP[a]
map<- raster(r)
for(k in AW){
for(j in km){
# deffine the directory
setwd(paste0("~/prodes/buff_",k,"/AP_rings"))
getwd()
# Call each SPDF
SPDF<- readOGR(".", paste0("ring",k,j, i))
names(SPDF)[names(rings) == "X__i__"] <- "TIPO"
# reproject the SPDF to ALbers
rings <- spTransform(rings, CRSobj = "+proj=longlat +ellps=GRS80
+towgs84=0,0,0,0,0,0,0 +no_defs ")
#Extract the pixels values
( extrc <- extract(map, SPDF, na.rm=T) )
#proportion calculation for each class
(class.prop = lapply(extrc, function(x)
{prop.table(table(factor(x,levels=c(0,1))))}))
p.prop = setNames(
do.call(
rbind.data.frame,
class.prop),
c("Desmatado","natural"))
p.prop$ID<-seq_along(p.prop[,1])
rings$ID<- 1:length(SPDF)
freq <- merge(SPDF, p.prop) #add to polygons
frequenc<-as.data.frame(freq)
View(frequenc)
results <- rbind(results, frequenc)
setwd("~/prodes/resultados")
write.table(results, file="resultados.txt", sep="\t", row.names=F)
}
}
}
Error: In this point from my code above
( extrc <- extract(ras_PI, rings, na.rm=T) )
Cannot allocate large size vector 225.4 mb
The message seems pretty clear. You are extracting a lot of data.
So there are either very many rings and/or they are rather large. So you may need to either provide a function argument to extract or loop over the rings.
Perhaps you are doing something wrong ---- but there is no for us to tell as you are referring to data that we do not have. show(rings) could be helpful
Related
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.
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
I'm trying to plot rainfall data from weather radar. Data file is 900x900 points matrix (900x900km). Projection informations from original cappi file:
<projection lat_lr="48.133400" lat_ul="56.186500" type="aeqd" lon_lr="25.157600" size_x="900" size_y="900" lon_ul="11.812900">
<lon_0>19.092600</lon_0>
<lat_0>52.346800</lat_0>
<ellps>+ellps=sphere</ellps>
</projection>
I'm reading data file (example: https://meteomodel.pl/examples/out.txt ) to matrix, and convert to raster:
a1 = as.matrix(read.table("/home/user/out.txt", header=F, as.is=TRUE))
a1[a1==0] <- NA
maxDBz <- 95.5
minDBz <- -31.5
step <- (maxDBz - minDBz) / 254
a1 <- minDBz + (a1 * step)
r <- raster(a1)
Then I'm trying to set extent and CRS:
e <- extent(11.812900, 25.157600, 48.133400, 56.186500)
r <- setExtent(r, e)
crs(r) <- "+proj=aeqd +lat_0=52.346800 +lon_0=19.092600 +x_0=900 +y_0=900 +ellps=sphere +datum=WGS84 +units=km +no_defs"
Data are plotted, however projection is incorrect:
https://meteomodel.pl/examples/Rplot01.png
Correct image from Polish Institute of Meteorology and Water Management:
https://meteomodel.pl/examples/cappi.png
What am I doing wrong?
What you are doing wrong is setting the extent using lon/lat crs, whereas the data have "+proj=aeqd. These need to match.
I do not know what the correct extent is, but you can approximate it like this:
p <- "+proj=aeqd +lat_0=52.346800 +lon_0=19.092600 +x_0=900 +y_0=900 +ellps=sphere +datum=WGS84 +units=km +no_defs"
e <- extent(11.812900, 25.157600, 48.133400, 56.186500)
r <- raster()
extent(r) <- e
rr <- projectExtent(r, p)
extent(rr)
#class : Extent
#xmin : -541.0182
#xmax : 452.2122
#ymin : -488.8849
#ymax : 431.1854
The txt file provided sugests that the extent you want is
e <- extent(-449997.470, 451000.522, -451003.637, 449998.274)
And that suggests that the units in your crs should be m, not km
p <- "+proj=aeqd +lat_0=52.346800 +lon_0=19.092600 +x_0=900 +y_0=900 +ellps=sphere +units=m "
Given a rasterLayer a,
library(raster)
library(rasterVis)
a=raster('p190001.grd')
head(a)
Based on the description below (see below) which is also found in this link,
ftp://ccrp.tor.ec.gc.ca/pub/EC_data/CANGRD/
I came up with the following CRS
mycrs <- CRS("+proj=stere +lat_0=90 +lat_ts=60 +lon_0=-110 +x_0=1884770 +y_0=5220000 +datum=WGS84 +to_meter=50000")
proj4string(a) <- mycrs
projection(a) <- mycrs
a
class : RasterLayer
dimensions : 95, 125, 11875 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : -0.5, 124.5, -0.5, 94.5 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=stere +lat_0=90 +lat_ts=60 +lon_0=-110 +x_0=1884770 +y_0=5220000 +datum=WGS84 +to_meter=50000 +ellps=WGS84 +towgs84=0,0,0
data source : in memory
names : p190001
values : 4.59, 335.45 (min, max)
a[a==170141000918782798866653488190622531584.00]=NA # change missing value identifier
levelplot(a)
For the sake of completeness, I have created a .Rdata file ~209 KB which can be found here.
The intention is to collapse the a to a dataframe and perform some analysis on it then do a rasterFROMXY. However, I get the error:
Error in rasterFromXYZ(dt) : x cell sizes are not regular
My code:
library(data.table)
v <- getValues(a) # get vector
dt <- as.data.table(v)
# Add LATITUDE and LONGITUDE columns to dt
dt[,LATITUDE:=grid_pnt_lls$y]
dt[,LONGITUDE:=grid_pnt_lls$x]
dtnames <- c(names(dt)[2:3],names(dt)[1])
setcolorder(dt,dtnames)
vcols <- c('LONGITUDE','LATITUDE','v')
setcolorder(dt,vcols)
library(data.table)
setnames(dt, "LONGITUDE", "x")
setnames(dt, "LATITUDE", "y")
setnames(dt, "v", "z")
ras=rasterFromXYZ(dt)# Error in rasterFromXYZ(dt) : x cell sizes are not regular
As a workaround, I tried to projectRaster to regular latlon (projj <- CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0")
) and even rasterrizebut could not get the original dimensions of a. I would like rasto have same dimensions as a but on latlon grid.
#===========================================================================
The CANGRD grid is in polar stereographic projection with a 50 km spatial resolution. The grid is a 125 (columns) by 95 (rows) matrix, where the SW corner (0,0) is at 40.0451°N latitude and 129.8530°W longitude. The projection is true at 60.0°N and centered on 110.0°W. The file ‘CANGRD_points_LL.txt’ lists the latitudes and longitudes for each grid point.
The general format of the ‘YYYYDD.grd’ file is:
Id – ‘DSAA’ identifies the file as an ASCII grid file
nx ny - nx is the integer number of grid lines along the X axis (columns)
ny is the integer number of grid lines along the Y axis (rows)
xlo xhi - xlo is the minimum X value of the grid
xhi is the maximum X value of the grid
ylo yhi - ylo is the minimum Y value of the grid
yhi is the maximum Y value of the grid
zlo zhi - are the minimum and maximum Z values of the grid.
Instead of using getValues use as.data.frame to convert raster to a dataframe.
dt <- data.table(as.data.frame(a, xy = TRUE))
setnames(dt, "p190001", "z")
## Sample Calculation on Values
dt[, z := z/2]
ras <- rasterFromXYZ(dt)
plot(ras)
this might be rather simple, but I am a novice in R. I have tried for awhile now to plot two rasters against each other using boxplot from the package raster.
I have a DEM raster and a categorical raster that contains 4 cluster groups, which I would like to use as 'zones' as described in the manual:
boxplot(x, y=NULL, maxpixels=100000, ...)
x Raster* object
y If x is a RasterLayer object, y can be an additional RasterLayer to group the
values of x by ’zone’
> DEM
class : RasterLayer
dimensions : 12381, 61922, 766656282 (nrow, ncol, ncell)
resolution : 0.1, 0.1 (x, y)
extent : 478307.4, 484499.6, 6131862, 6133100 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs
data source : /Users/Yvonne/Desktop/Boxplot/Ribe_DEM_0.1m.tif
names : Ribe_DEM_0.1m
values : -7.523334, -0.36 (min, max)
> Cluster
class : RasterLayer
dimensions : 12381, 61922, 766656282 (nrow, ncol, ncell)
resolution : 0.1, 0.1 (x, y)
extent : 478307.4, 484499.6, 6131862, 6133100 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs
data source : /Users/Yvonne/Desktop/Boxplot/final_cluster.tif
names : final_cluster
values : 1, 4 (min, max)
attributes :
ID Rowid COUNT
1 0 463524
2 1 4118997
3 2 3390160
4 3 3218998
> boxplot(DEM, Cluster, xlab="Cluster", ylab="Elevation")
Error in parse(text = x, keep.source = FALSE) :
<text>:2:0: unexpected end of input
1: ~
^
In addition: Warning message:
In .local(x, ...) : taking a sample of 1e+05 cells
Update:
I just found a working example, which does exactly what I want. However if I run it with my own data I always get above error. Maybe someone could explain the error message. Would be really appreciated.
r1 <- r2 <- r3 <- raster(ncol=10, nrow=10)
r1[] <- rnorm(ncell(r1), 100, 40)
r2[] <- rnorm(ncell(r1), 80, 10)
r3[] <- rnorm(ncell(r1), 120, 30)
s <- stack(r1, r2, r3)
names(s) <- c('A', 'B', 'C')
rc <- round(r1[[1]]/100)
hist(rc)
summary(rc)
boxplot(s[[1]],rc)
Okey I found an answer, I don't know exactly why but it works for me:
I had to create a brick and then I could use the boxplot as mentioned above.
s <- stack(DEM, Cluster)
sbrick <- brick(s)
boxplot(sbrick[[1]], sbrick[[2]], xlab="Cluster", ylab="Elevation")
Resulting in this plot boxplot DEM against cluster groups
Thanks everyone for their help!
You can use bwplot function in rasterVis library.
Here is an example from rasterVis:
library(raster)
library(rasterVis)
r <- raster(system.file("external/test.grd", package="raster"))
s <- stack(r, r*2)
bwplot(s,violin=FALSE,strip=strip.custom(strip.levels=TRUE))
It is not clear to me why you get that error. Perhaps you can run the code below and see for yourself:
x <- stack(DEM, Cluster)
s <- sampleRegular(s, 100000, useGDAL=TRUE)
cn <- colnames(s)
f <- as.formula(paste(cn[1], '~', cn[2]))
boxplot(f, data=s)
Perhaps you should only provide your raster values as a vector and let the boxplot() function do the rest by:
boxplot(values(DEM) ~ values(Cluster), xlab="Cluster", ylab="Elevation")
Note that this will only work if both DEM and Cluster are exactly the same extent and resolution.