rr-stars

How can I extract values from one stars object using the extent of another stars object in R?


I am new-ish to using the stars package in R and I am having trouble with figuring out how to create a stars object C that has the values from object A but the extent of object B. Specifically, I have a map of average spring temperatures in Europe (Object A) and I want to crop it using a separate stars object containing presence of deciduous broadleaf forests (Object B).

Object A: https://i.sstatic.net/DQsZn.jpg

> CRU.SpringT.2009.2018_EU
stars object with 2 dimensions and 1 attribute
attribute(s):
                                   Min.  1st Qu.   Median     Mean  3rd Qu.     Max.   NA's
CRU.SpringT.2009.2018_EU.tif  -15.81895 1.201286 5.480992 4.979221 8.204463 17.55605 310479
dimension(s):
  from   to offset      delta refsys point values x/y
x    1 1440    -10  0.0416667 WGS 84 FALSE   NULL [x]
y    1  672     65 -0.0416667 WGS 84 FALSE   NULL [y]

Object B: https://i.sstatic.net/6dons.jpg

> Dec.BL_EU3
stars_proxy object with 1 attribute in 1 file(s):
$Consensus_reduced_class_3.tif
[1] "[...]/Consensus_reduced_class_3.tif"

dimension(s):
   from    to offset       delta                       refsys point values x/y
x 20401 27600   -180  0.00833333 +proj=longlat +datum=WGS8... FALSE   NULL [x]
y  3001  6360     90 -0.00833333 +proj=longlat +datum=WGS8... FALSE   NULL [y]
call_list:
[[1]]
x[i = i, drop = drop, crop = crop]
attr(,".Environment")
<environment: 0x000002a17a1ecac0>

[[2]]
x[i = i, drop = drop, crop = crop]
attr(,".Environment")
<environment: 0x000002a178d61dc0>

[[3]]
e1/e2
attr(,".Environment")
<environment: 0x000002a177987b10>

Both objects are cropped using the same bbox. The goal is for the resulting object (Object C) to have the extent of B but with the temperature values from A.

Dropbox links to tif files:

Object A: https://www.dropbox.com/s/lwvdxnis7k38e18/CRU.SpringT.2009.2018_EU.tif?dl=0

Object B: https://www.dropbox.com/s/uybxk40z853mu7a/EU%20Dec%20Broadleaf.tif?dl=0


Solution

  • That's it! It's much easier with the files :-) Please find below one possible solution to your problem. It works on my computer. I hope it will be the same for you :-)

    I have deliberately detailed the code to make it easier for you to understand it. Of course, you can modify the form to make it more compact if needed.

    PSEUDO Reprex !!

    library(sf)
    library(stars)
    library(ggplot2)
    
    A <- read_stars("CRU.SpringT.2009.2018_EU.tif")
    B <- read_stars("consensus_full_class_3.tif")
    
    # First step: Transform B to have the same extent and resolution of A
    B_cropped_resample <- st_warp(B, A, use_gdal = TRUE)
    
    
    # Second step: convert 0 to NA values in your object B (i.e. deciduous forests)
    B_cropped_resample[B_cropped_resample == 0] <- NA # B should contain only NA and 1 values 
    
    
    # Third step: convert B into `sf` object with 'points' geometry
    B_cropped_resample_sf <- st_as_sf(B_cropped_resample, as_points = TRUE, na.rm = TRUE)
    
    
    # Fourth step : extract values of object A with the object `B_cropped_resample_sf`
    C <- st_extract(A, B_cropped_resample_sf) # C is a sf object which contains the 
                                              # values of A at the corresponding points
    
    # Sixth step: convert 'sf' object back into stars 'object' and split 'sf' point 
    # geometry into two 'stars' dimensions
    C <- st_as_stars(C, name = attr(C, "CRU.SpringT.2009.2018_EU.tif", "geometry"))
    C <- st_sfc2xy(C)
    
    
    # Seventh step: plot the resulting 'stars' object which shows the temperatures (i.e.  
    # values from object A) for each deciduous forest (i.e. locations from object B)
    ggplot2::ggplot() + geom_stars(data = C) +
      coord_equal()
    

    Please find the image obtained after having run the code:

    enter image description here