Search code examples
geospatialtiffr-rasterterra

Difference between a A terra SpatRaster object and a Formal Class Rasterlayer


What is the difference between a A terra SpatRaster generated from terra and a Formal class raster layer generated by raster, if both are derived from the same raster file, let's say a tif?


Solution

  • They are instances of different classes defined in different R packages. They are not directly related in any way. And it does not matter whether they were constructed by reading the same file or not.

    Likewise, you can represent the number 10 in many different ways (by different classes).

    x <- 10
    y <- list(10)
    z <- data.frame(d=10)
    a <- matrix(10)
    

    You can use class to find out what class an object belongs to

    class(x)
    #[1] "numeric"
    class(y)
    #[1] "list"
    class(z)
    #[1] "data.frame"
    class(a)
    #[1] "matrix" "array" 
    

    And you can often coerce an object from one class to another.

    b <- as.data.frame(a)
    class(a)
    #[1] "matrix" "array" 
    class(b)
    #[1] "data.frame"
    

    But there are things you can do with a matrix that you cannot do with a data.frame and vice versa.

    Note that we also have generic functions. That is, functions that are implemented for objects of different classes. So you can do

    nrow(a)
    #[1] 1
    nrow(z) 
    #[1] 1
    

    And even

    nrow(x)
    #NULL
    

    You can also use nrow with a SpatRaster and RasterLayer.

    The meaning of the value returned by a generic function may depend on the object type that you are using. For example, compare the use of length for two objects of different classes holding the same numbers.

    length(1:3)
    #[1] 3
    length(data.frame(v=1:3))
    #[1] 1
    

    Finally, with these generic functions, the actual implementation of the function that is used depends on the class of the object. Therefore, with SpatRaster x the below function calls are identical (the both call the nrow method implemented in "terra".

    library(terra)
    x <- rast(nrow=1, ncol=1, vals=10)
    terra::nrow(x)
    #[1] 1
    raster::nrow(x)
    #[1] 1
    

    You do not provide a motivation for your question. In your previous question you are using the "raster" and "terra" packages at the same time. That is possible but it can easily lead to confusion because they are so similar (as illustrated by that question). See the top and the bottom of the page returned by ?terra::terra for some of the major differences.

    Once you start using "terra" it is best stick with that, but if you need Raster* objects, for use with a package that only supports that class, you can coerce a SpatRaster to a RasterLayer or RasterStack like this

    library(raster)
    r <- raster(x)
    s <- stack(x) 
    b <- brick(r)
    
    # or let the software determine whether you get a Layer, Stack or Brick
    y <- as(x, "Raster")
    

    Inspect what classes they belong to

    class(x)
    #[1] "SpatRaster"
    #attr(,"package")
    #[1] "terra"
    class(y)
    #[1] "RasterLayer"
    #attr(,"package")
    #[1] "raster"
    

    And you can take a Raster object to terra like this

    rr <- rast(s)
    
    rr
    #class       : SpatRaster 
    #dimensions  : 1, 1, 1  (nrow, ncol, nlyr)
    #resolution  : 360, 180  (x, y)
    #extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
    #coord. ref. : +proj=longlat +datum=WGS84 +no_defs 
    #source(s)   : memory
    #name        : lyr.1 
    #min value   :    10 
    #max value   :    10