rfor-loopkriginggstat

Local Block Kriging with Local Variogram with gstat


I have been unable to find any information specific to local block kriging with a local variogram using the gstat package in R. There is freeware called VESPER from the Australian Center for Precision Agriculture that is able to do this, and from what I have read it should be possible in R, I could just use some help with putting together a for-loop to make the gstat functions work locally.

Using the meuse data set as an example, I have been able to calculate and fit a global variogram to a data set:

    library(gstat)
    data(meuse)
    coordinates(meuse) = ~x+y
    data(meuse.grid)
    gridded(meuse.grid) = ~x+y

    logzinc_vgm<- variogram(log(zinc)~1, meuse)
    logzinc_vgm_fit <- fit.variogram(logzinc_vgm, model=vgm("Sph", "Exp"))
    logzinc_vgm_fit

    plot(logzinc_vgm, logzinc_vgm_fit)

This gives a nice plot of the variogram for the whole data set with the fitted model. Then I can use this to perform block kriging over the entire data set:

    logzinc_blkkrig <- krige(log(zinc)~1, meuse, meuse.grid, model = logzinc_vgm_fit, block=c(100,100))
    spplot(logzinc_blkkrig["var1.pred"], main = "ordinary kriging predictions")
    spplot(logzinc_blkkrig["var1.var"],  main = "ordinary kriging variance")

This produces a plot of the interpolated data as well as a plot of the variance for each predicted point. So this would be perfect if I wanted these functions to work once for my entire data set...

But I have been unable to generate a for-loop to handle these functions on a local level.

My goals are: 1. For each point in my grid file (which I have tried as both a data frame and SpatialPointsDataFrame), I would like to subset from my data file points within the distance diagonally of the range given in the global variogram (easy to call this location (i.e. logzinc_vgm_fit[2,3])) 2. On this subset of data, I would like to calculate the variogram (as above) and fit a model to it (as above) 3. Based on this model, I would like to perform block kriging to get a predicted value and variance at that grid point 4. Build the above three steps into a for-loop to predict values at each grid point based on the local variogram around each grid point

note: as with the meuse data set built into the gstat package, the dimensions of my grid and data data frames are different

Thank you very much for chiming in if anyone is able to tackle this question. Happy to post the code I am working with so far if it would be useful.


Solution

  • I made a for loop that I think accomplishes what you request. I do not think that block kriging is required for this because the loop predicts at each grid cell.

    The rad parameter is the search radius, which can be set to other quantities, but currently references the global variogram range (with nugget effect). I think it would be best to search a little further for points because if you only search up to the global variogram range, a local variogram fit may not converge (i.e. no observed range).

    The k parameter is for the minimum number of nearest neighbors within rad. This is important because some locations may have no points within rad, which would result in an error.

    You should note that the way you specified model=vgm("Sph", "Exp") seems to take the first listed method. So, I used the Spherical model in the for loop, but you can change to what you want to use. Matern may be a good choice if you think the shape will change with location.

    #Specify the search radius for the local variogram
    rad = logzinc_vgm_fit[2,3]
    #Specify minimum number of points for prediction
    k = 25
    #Index to indicate if any result has been stored yet
    stored = 0
    for (i in 1:nrow(meuse.grid)){
      #Calculate the Euclidian distance to all points from the currect grid cell
      dists = spDistsN1(pts = meuse, pt = meuse.grid[i,], longlat = FALSE)
    
      #Find indices of the points within rad of this grid point
      IndsInRad = which(dists < rad)
    
      if (length(IndsInRad) < k){
        print('Not enough nearest neighbors')
      }else{
        #Calculate the local variogram with these points
        locVario = variogram(log(zinc)~1, meuse[IndsInRad,])
    
        #Fit the local variogram
        locVarioFit = fit.variogram(logzinc_vgm, model=vgm("Sph"))
    
        #Use kriging to predict at grid cell i. Supress printed output.
        loc_krig <- krige(log(zinc)~1, meuse[IndsInRad,], meuse.grid[i,], model = locVarioFit, debug.level = 0)
    
        #Add result to database
        if (stored == 0){
          FinalResult = loc_krig
          stored = 1
        }else{
          FinalResult = rbind(FinalResult, loc_krig)
        }
      }
    }