Search code examples
rterra

How to properly subset data using their variable names in terra?


Let's say I have a SpatRaster data containing 2 variables. One of them is called "elev", and the other is called "relative_elev":

library(terra)
f = system.file("ex/elev.tif", package="terra")
r1 = rast(f)
r2 = rast(f)
varnames(r2) = "relative_elev"
r_combined = c(r1, r2)

Checking the variable names:

varnames(r_combined)
#[1] "elev"          "relative_elev"

I want to subset data based on their names. When I do r_combined["elev"] I expect to get only the elev data, but I get both "elev" and "relative_elev":

r_combined["elev"]
#class       : SpatRaster 
#dimensions  : 90, 95, 2  (nrow, ncol, nlyr)
#resolution  : 0.008333333, 0.008333333  (x, y)
#extent      : 5.741667, 6.533333, 49.44167, 50.19167  (xmin, xmax, ymin, ymax)
#coord. ref. : lon/lat WGS 84 (EPSG:4326) 
#sources     : elev.tif  
#              elev.tif  
#varnames    : elev 
#              relative_elev 
#names       : elevation, elevation 
#min values  :       141,       141 
#max values  :       547,       547 

When I do r_combined["relative_elev"] I get an error:

r_combined["relative_elev"]
#Error: [subset] no (valid) layer selected

Both behaviours are very unexpected and confusing to me.


Solution

  • names refers to layers, varnames to variables or sub-datasets. varnames can be used to extract a sub-dataset (variable) from a SpatRasterDataset.

    s <- sds(r1, r2)
    s
    #class       : SpatRasterDataset 
    #subdatasets : 2 
    #dimensions  : 90, 95 (nrow, ncol)
    #nlyr        : 1, 1 
    #resolution  : 0.008333333, 0.008333333  (x, y)
    #extent      : 5.741667, 6.533333, 49.44167, 50.19167  (xmin, xmax, ymin, ymax)
    #coord. ref. : lon/lat WGS 84 (EPSG:4326) 
    #source(s)   : elev.tif 
    #names       : elev, relative_elev 
    
    
    s["relative_elev"]
    #class       : SpatRaster 
    #dimensions  : 90, 95, 1  (nrow, ncol, nlyr)
    #resolution  : 0.008333333, 0.008333333  (x, y)
    #extent      : 5.741667, 6.533333, 49.44167, 50.19167  (xmin, xmax, ymin, ymax)
    #coord. ref. : lon/lat WGS 84 (EPSG:4326) 
    #source      : elev.tif 
    #varname     : relative_elev 
    #name        : elevation 
    #min value   :       141 
    #max value   :       547 
    

    To be able to subset like this, perhaps you should read your file with sds(filename) instead of rast(filename).