0

I have a data frame of non-uniformly spaced lat/lon positions and values for a series of continuous and categorical variables associated with each position. I would like to convert this data frame to a raster stack in R.

I am able to do this for the continuous variables in my dataset by using the following steps:

#data frame of continuous data
df.cont = data.frame(x = c(-91.93858, -91.93594, -86.64036, -86.64308, -86.65414, -86.68534, -86.70639, -86.68607, -86.71138, -86.80578),
                     y = c(46.54691, 46.51794, 46.40897, 46.38674, 46.38863, 46.38288, 46.36599, 46.38356, 46.38376, 46.39007),
                     v1 = c(-0.2747070, -0.2747070, -0.5369783, -0.5369783, -0.5369783, -0.5369783, -0.5369783, -0.5369783, -0.5369783, -0.6989145),
                     v2 = c(-0.3509326, -0.3509326, -0.3509326, -0.3509326, -0.3509326, -0.3509326, -0.3509326, -0.3509326, -0.3509326, -0.3509326),
                     v3 = c(-0.03135792, -0.75269812,  0.29461748,  0.19176132, -0.20611817, -0.67954751, -0.80617701, -0.25480716, -0.77835544, -0.78567822))

#convert to matrix
mat.cont = as.matrix(df.cont)

#define non-uniform spatial extent
e.cont = terra::ext(mat.cont[,1:2])

#create raster
r.cont = terra::rast(e.cont)

#populate raster
x.cont = terra::rasterize(mat.cont[,1:2], r.cont, mat.cont[,3:5], fun = mean)

However, I can't figure out how to do this for the categorical variables in my dataset:

#data frame of categorical data
df.cat = data.frame(x = c(-91.93858, -91.93594, -86.64036, -86.64308, -86.65414, -86.68534, -86.70639, -86.68607, -86.71138, -86.80578),
                    y = c(46.54691, 46.51794, 46.40897, 46.38674, 46.38863, 46.38288, 46.36599, 46.38356, 46.38376, 46.39007),
                    v1 = factor(c("desert", "desert", "desert", "forest", "forest", "beach", "forest", "desert", "beach", "forest")),
                    v2 = factor(c(0, 0, 1, 0, 1, 1, 1, 0, 0, 1)))

#convert to matrix
mat.cat = as.matrix(df.cat)

#define non-uniform spatial extent
e.cat = terra::ext(mat.cat[,1:2])

I get the following error when attempting to create the spatial extent for the categorical data:

unable to find an inherited method for function ‘ext’ for signature ‘"character"’

I think this is probably because mat.cat is formatted as a character matrix due to the presence of non-numeric variables, whereas mat.cont is a numeric matrix.

Either way, I'm unsure of how to handle the categorical data. I'm also wondering if there is a way to handle the continuous and categorical data together when creating the raster stack, instead of handling these data separately (with a plan of combining into a single stack at the end...I'm assuming this is possible to do).

Any tips would be extremely helpful! I've seen similar questions posted here but they all seem to be tailored to continuous data or uniformly gridded lat/lon positions. Thanks!

1
  • Rasters cannot contain character data, only numeric. You will need to encode your classes (factors) as numeric then crosswalk them in an associated attribute table. You can use terra::as.factor then assign the data.frame as levels. When you write the data out there will then be an associated dbf file. Take a look at ?ratify Apr 26 at 20:58

1 Answer 1

2

rasterizing categorical data works well for lines and polygons, but I had not considered it for points. I will built that into a future version, but for now you can do:

library(terra)
df.cat = data.frame(x = c(-91.93858, -91.93594, -86.64036, -86.64308, -86.65414, -86.68534, -86.70639, -86.68607, -86.71138, -86.80578),
                    y = c(46.54691, 46.51794, 46.40897, 46.38674, 46.38863, 46.38288, 46.36599, 46.38356, 46.38376, 46.39007),
                    v1 = factor(c("desert", "desert", "desert", "forest", "forest", "beach", "forest", "desert", "beach", "forest")),
                    v2 = factor(c(0, 0, 1, 0, 1, 1, 1, 0, 0, 1)))


v <- vect(df.cat, geom=c("x", "y"))
r <- rast(terra::ext(v))

x1 <- terra::rasterize(v, r, "v1", fun=raster::modal)
levels(x1) <- unique(data.frame(id=as.integer(v$v1)-1, v1=v$v1))

x2 <- terra::rasterize(v, r, "v2", fun=raster::modal)
levels(x2) <- unique(data.frame(id=as.integer(v$v2)-1, v2=v$v2))

x <- c(x1, x2)
1
  • This worked perfectly, thanks so much for your help!
    – nrcombs
    Apr 27 at 18:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.