Search code examples
rlatitude-longitudebioinformaticsmeanbiometrics

How do I calculate the mean of two different variables taking into account the values of latitude and longitude in R?


I am currently trying to obtain some data in R from a table.

I have a dataset with two different variables, the annual range and the annual mean, of the worldwide sea surface temperature (SST). I have these values for each latitude (from 90 to -90) and longitude (from 180 to -180) level.

I would like to obtain the mean of the aforementioned variables (annual range and annual mean) for 5x5 grid cells of latitude/longitude. For example, I would need to know the "annual range" mean for for a longitude between -180 and -176 and a latitude between 90 and 86, and so on until getting the mean of this variable for all the possible 5x5 grid cells.

My data looks like:

lon lat ANNUAL_MEAN ANNUAL_RANGE 1 0.5 89.5 -1.8 0 2 1.5 89.5 -1.8 0 3 2.5 89.5 -1.8 0 4 3.5 89.5 -1.8 0 5 4.5 89.5 -1.8 0 6 5.5 89.5 -1.8 0 ... 52001 354.5 -89.5 -1.8 0 52002 355.5 -89.5 -1.8 0 52003 356.5 -89.5 -1.8 0 52004 357.5 -89.5 -1.8 0 52005 358.5 -89.5 -1.8 0 52006 359.5 -89.5 -1.8 0

Thank you in advance


Solution

  • You can use raster package and its focal function for computations with a moving window.

    First I will create a dummy data.frame which represents your data

    # Prepare dummy data.frame
    set.seed(2222)
    lonlat <- expand.grid(1:10, 1:10)
    df <- data.frame( lon = lonlat[, 1],
                      lat = lonlat[, 2],
                      ANNUAL_MEAN = rnorm(100),
                      ANNUAL_RANGE = runif(100, 1, 5)
                    )
    

    Now we have to convert data frame into raster and to perform a moving window averaging.

    library(raster)
    
    # Convert data frame to raster object
    rdf <- df
    coordinates(rdf) <- ~ lon + lat
    gridded(rdf) <- TRUE
    rdf <- brick(rdf) # our raster brick
    
    ## Perform moving window averaging
    
    # prepare weights matrix (5*5)
    w <- matrix(1, ncol = 5, nrow = 5)
    
    # perform moving window averaging
    ANNUAL_MEAN_AVG <- focal(rdf[[1]], w, mean, pad = TRUE, na.rm = TRUE)
    ANNUAL_RANGE_AVG <- focal(rdf[[2]], w, mean, pad = TRUE, na.rm = TRUE)
    
    # Append new data to initial data.frame
    df$ANNUAL_MEAN_AVG <- as.data.frame(ANNUAL_MEAN_AVG)
    df$ANNUAL_RANGE_AVG <- as.data.frame(ANNUAL_RANGE_AVG)
    

    Now each cell in df$ANNUAL_MEAN_AVG and df$ANNUAL_RANGE_AVG contains the mean value of the corresponding 5*5 square.

    UPD 1. 5x5 downsampling

    If you need a fixed 5x5 grid cells with mean values per cell you can use raster::agregate function.

    Working with rdf raster brick from the previous example.

    # perform an aggregation with given downsampling factor
    rdf_d <- aggregate(rdf, fact=5, fun = mean)
    
    # Now each pixel in the raster `rdf_d` contains a mean value of 5x5 pixels from initial `rdf`
    # we need to get pixels coordinates and their values
    coord <- coordinates(rdf_d)
    vals <- as.data.frame(rdf_d)
    colnames(coord) <- c("lon", "lat")
    colnames(vals) <- c("ANNUAL_MEAN_AVG", "ANNUAL_RANGE_AVG")
    
    res <- cbind(coord, vals)