In terra I have an existing raster with values range from 1 to 4 in the following proportions.
“1” appears 5 times; “2” 15 times; “3” 20 times; “4” 60 times
I need to create a new raster with a different shape and extent, and randomly assign the same values 1 to 4 in the same proportion of occurrence as the previous raster.
How do I go about populating NEW.RASTER?
r <- rast(ncol=10,nrow=10, vals=1)
> r[6:20] <- 2
> r[21:40]<-3
> r[41:100] <- 4
> r
class : SpatRaster
dimensions : 10, 10, 1 (nrow, ncol, nlyr)
resolution : 36, 18 (x, y)
extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
coord. ref. : lon/lat WGS 84 (CRS84) (OGC:CRS84)
source(s) : memory
name : lyr.1
min value : 1
max value : 4
> freq(r)
layer value count
1 1 1 5
2 1 2 15
3 1 3 20
4 1 4 60
>
> NEW.RASTER <- rast(ncol=15,nrow=350)
> NEW.RASTER
class : SpatRaster
dimensions : 350, 15, 1 (nrow, ncol, nlyr)
resolution : 24, 0.5142857 (x, y)
extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
coord. ref. : lon/lat WGS 84 (CRS84) (OGC:CRS84)
You can obtain a sample equal to the number of pixels in the new raster, containing only the values of interest (1:4), and using the proportion in your original raster as the probability weight. Then you just need to assign them to the new raster.
library(terra)
# Get frequencies and calculate their proportion
df_f <- freq(r)
tot <- sum(df_f$count)
df_f$prop <- df_f$count/tot
df_f
# layer value count prop
#1 1 1 5 0.05
#2 1 2 15 0.15
#3 1 3 20 0.20
#4 1 4 60 0.60
# Get number of pixels in the new rasters
npix <- ncell(NEW.RASTER)
# Sample the values of interest
set.seed(8)
vals <- sample(df_f$value, npix, replace = TRUE, prob = df_f$prop)
# Calculate new proportions just to check (they will be closely similar)
df <- as.data.frame(table(vals))
df$prop <- df$Freq/npix
df
# vals Freq prop
#1 1 270 0.05142857
#2 2 790 0.15047619
#3 3 1072 0.20419048
#4 4 3118 0.59390476
# Assign the values to the new raster
values(NEW.RASTER)<-vals
0
Thank you Jonathan – this has worked and brings me great flexibility – much appreciated. There had also been a reply from @Robert Hijmans which was very useful; it achieved the same yet carried forward proportion of NA values if necessary. This was as follows
r <- rast(ncol=10,nrow=10, vals=1)
r[1:2] <- NA
r[6:20] <- 2
r[21:40]<-3
r[41:100] <- 4
NEW.RASTER <- rast(ncol=15,nrow=350)
NEW.RASTER <- setValues(NEW.RASTER, sample(values(r)))
summary(r)
lyr.1
Min. :1.000
1st Qu.:3.000
Median :4.000
Mean :3.398
3rd Qu.:4.000
Max. :4.000
NA's :2
> summary(NEW.RASTER)
lyr.1
Min. :1.0
1st Qu.:3.0
Median :4.0
Mean :3.4
3rd Qu.:4.0
Max. :4.0
NA's :105