I have a SpatVect consisting of points and I want to rasterize them into a SpatRaster with a given resolution. Is there a way of specifying a function taking in the points that are within a buffer of each raster cell?
Many thanks
Joao
-- Update --
Maybe a figure would help understand what I'm after with my question. The red square will have to be run over the center of each pixel to calculate some statistics using the ovelaying points. Apologies for the clumsy question, but I hope the figure is clear enough...
terra version 1.6-28 supports rasterization of points with a rectangular moving window.
Example data
library(terra)
#terra 1.6.33
r <- rast(ncol=100, nrow=100, crs="local", xmin=0, xmax=50, ymin=0, ymax=50)
set.seed(100)
x <- runif(50, 5, 45)
y <- runif(50, 5, 45)
z <- sample(50)
v <- vect(data.frame(x,y,z), geom=c("x", "y"))
Solution
r1 <- rasterizeWin(v, r, field="z", fun="count", pars=10, win="rectangle")
plot(r1)
points(x, y)
You can change fun to another function that works for you, and you can change the size of the moving window with pars.
Instead of a rectangle, you can also use a circle or an ellipse. The border of a circular window is equidistant from the center of the cells. In contrast, the border of rectangles are at a constant distance from the border of the grid cells in most directions (not at the corners). Here is an example.
r2 <- rasterizeWin(v, r, field="z", fun="count", pars=5.25, win="circle")
plot(r2)
You can also use buffers around each cell to get a window that is truly equidistant from each cell border.
r3 <- rasterizeWin(v, r, field="z", fun=length, pars=5, win="buf")
plot(r3)
In this case, because the buffer size is large relative to the cell size, the result is very similar to what you get when using a circular window. Using "circle" should be the fastest, and using "buffer" should be the slowest in most cases. The function should now in all cases be memory-safe, except, perhaps when using very large buffers (more could be done if need be).
Version 1.6-28 is currently the development version. You can install it with
install.packages('terra', repos='https://rspatial.r-universe.dev')
The approach you take seems to depend on what result you're looking for from the above and the relationship they have with each other.
library(terra)
`terra::buffer(` # both SpatVectx/SpatRastery, to distance in 'm'
`terra::buffer(` # that is meaningful
#take Rasty to SpatVecty
`terra::as.polygons(`, #then
`z<-terra::intersection(SpatVectx, SpatVecty)`
then back to SpatRastz? terra::mask or crop, might also be useful, again depending on where things are going next.
Related
I have a large raster with 3 values (1,2,3).
I want to create a zone of 20 meters for areas with value 3, but I want the buffer to be not outside (around) the areas of value 3 but inside these areas.
I have tried to use
my_zones<- buffer(my_raster, width=20)
but this creates a buffer of 20 m around and outside of all classes.
How can I transform this? my raster includes the entire Europe, so I would also like a relatively fast way to do the zones.
Can anyone help me?
EDIT1: I have also tried to creat a negative buffer like
buffer(my_raster, width=-20) but width cannot be negative.
EDIT2: I am not sure how to create a sample raster, so I tried the following with the terra package
my_raster <- rast(xmin=1, xmax=3, ymin=1, ymax=3, res=1, val=sample(1:4, 100^2, replace=T))
There is a negative buffer for polygons, but not for rasters. However you can inverse the process yourself.
Example data (you can always start with ?buffer for inspiration)
library(terra)
r <- rast(ncols=20, nrows=20, xmin=0, xmax=20, ymin=0, ymax=20, crs="local")
r[, 1:10] <- 1
A standard buffer
b <- buffer(r, width=5)
plot(b)
To get the negative buffer, first flip the cells that are NA, and then use buffer. The ! is to make the buffered area TRUE instead of FALSE
x <- ifel(is.na(r), 1, NA)
bb <- !buffer(x, width=5)
I have drawn an imaginary map for fun, and I thought it would be even more fun to make a DEM for the imaginary country using R, just to add to the visualization. :)
Basically, I now have a png with the outline of the country. Just only with a black border, the rest is left white.
My plan was to create a raster from it, so I could eventually add values to every pixel in the map. Since it's a imaginary map, it doesn't have a coordinate system. I just set the extent as it is as png:
drawing <- raster('drawing.png')
extent(drawing) <- c(0, 388, 0, 348)
Then I create a dataframe with the points of which eventually the DEM is calculated from. Basically, I just randomly select pixel locations within the country (name them x and y) and assign a random value as height. For this I use a simple excel sheet:
samples <- read_excel('samples.xlsx')
coordinates(samples) <- ~x+y
spatlocations <- SpatialPoints(samples)
vectlocations <- vect(samples)
Then, I thought, I could create a map using Inverse Distance Weighting (IDW), just to get a nice smooth gradient looking map. So it would possibly something like this:
result <- idw(unsampled, samples)
However, I fail to do this. I for example don't really know how to exactly work with the raster I created from the png, and the same for the sample points.
As you maybe can see, I am what you could consider a beginner :).
Is this possible at all? Is this methodology correct? How can I achieve such a map? Thanks in advance!
I'm trying to plot 3-dimensional vectors (x, y, z coordinates) onto a 3D coordinate system in R like in the picture below. Ideally, I would then like to construct 3d kernel density plots, also like in the image below.
Ideal result of vector plot and 3d kernel density plot
I have a matrix containing ~100 rows and one column for each coordinate (x, y , z). Initially, I tried arrow3D() from the plot3D package but I find the perspective to be sub-par, it's rather difficult to discern directions of the arrows from one perspective in the final plot. Next I tried the rgl package which gives me interactivity - great. Minimal working example:
library(rgl)
library(matlib)
data2 <- data.frame(replicate(6,rnorm(100))) #sample data set for minimum working example
colnames(data2) <- c("x_target", "y_target", "z_target", "x_start", "y_start", "z_start")
x1 <- data2$x_target - data2$x_start
y1 <- data2$y_target - data2$y_start
z1 <- data2$z_target - data2$z_start
vec <- (diag(6,3)) # coordinates for x, y and z axis
rownames(vec) <- c("X", "Y", "Z") # labels for x, y and z axis
z <- as.matrix((data.frame(x=x1, y=y1, z=z1)))
open3d()
vectors3d(vec, color=c(rep("black",3)), lwd=2, radius=1/25)
vectors3d(X=z, headlength=1/25)
(due to the random numbers generator the strange looking rods appear at different coordinates, not exactly like in the image i link to below)
The result of the code above is a version of the image link below. One set of coordinates produces a very strange looking more like rod object which is far longer then the coordinates would produce. If I plot the vectors individually, no such object is created. Anyone have any ideas why this happens? Also, if anyone has a tool (doesn't have to be R), that can create a 3D vector plot like in the first image, I'd be grateful. I find it to be very complicated in R, but I'm definitely a beginner.
Strange object to the right (long red rod that doesn't look like an arrow at all)
Thank you!
This is due to a bug in the matlib package, fixed in verson 0.9.2 of that package. I think you need to install it from Github instead of CRAN to get the bug fix:
devtools::install_github("friendly/matlib")
BTW, if you are using random numbers in a reproducible example, you can make it perfectly reproducible by something like
set.seed(123)
at the start (or some number other than 123). I saw reproducible problems with your example for set.seed(4).
I've been working with a spatial model which contains 21,000 grid cells of unequal size (i by j, where i is [1:175] and j is[1:120]). I have the latitude and longitude values in two seperate arrays (lat_array,lon_array) of i and j dimensions.
Plotting the coordinates:
> plot(lon_array, lat_array, main='Grid Coordinates')
Result:
My question: Is it possible to plot these spatial coordinates as a grid rather than as points? Does anyone know of a package or function that might be able to do this? I haven't been able to find anything online to this nature.
Thanks.
First of all it is always a bit dangerous to plot inherently spherical coordinates (lat,long) directly in the plane. Usually you should project them in some way, but I will leave it for you to explore the sp package and the function spTransform or something like that.
I guess in principle you could simply use the deldir package to calculate the Dirichlet tessellation of you points which would give you a nice grid. However, you need a bounding region for this to avoid large cells radiating out from the border of your region. I personally use spatstat to call deldir so I can't give you the direct commands in deldir, but in spatstat I would do something like:
library(spatstat)
plot(lon_array, lat_array, main='Grid Coordinates')
W <- clickpoly(add = TRUE) # Now click the region that contains your grid
i_na <- is.na(lon_array) | is.na(lat_array) # Index of NAs
X <- ppp(lon_array[!i_na], lat_array[!i_na], window = W)
grid <- dirichlet(X)
plot(grid)
I have not tested this yet and I will update this answer once I get the chance to test it with some artificial data. A major problem is the size of your dataset which may take a long time to calculate the Dirichlet tessellation of. I have only tried to call dirichlet on dataset of size up to 3000 points...
Is there a simple way to crop a specified pixel location of a png image, and raster that image onto a plot.
Currently i am working with dissociated cells (up to 1000 cells in a field of view). Each cell has a center x (in pixels) and a center y (in pixels). We gather data in trace format, so i would like a way of displaying the picture of the cells next to the trace.
I have tried rasterImage, and grid.raster. Unfortunately i have no idea how to call upon the image array to specify the location.
Also, i do not want to use the zoom package since the functions work extremely slow and are not able to raster onto a current plot.
Take a look at the raster package. The raster::raster function, for importing or coercing your png and raster::crop for subsetting to a specific extent.
Here is an example from the crop functions help.
Create an example raster
r <- raster(nrow=45, ncol=90)
r[] <- 1:ncell(r)
Subset the raster based on a define extent
e <- extent(-160, 10, 30, 60)
rc <- crop(r, e)
Plot results
par(mfrow=c(1,2))
plot(r)
plot(rc)
It was alot easier than expected. My PNG image was an array with 3 layers.
img[xpos, ypos, layer]
Therefore i could simply specify the location of my cells increased by a factor,
rasterImage(img[(x-x*.2):(x+x*.2), (y-y*.2):(y+y*.2),],-2, 4, 3, 1)
Now i need to code around for cells at the limits of my plots.