R/uncorrelationTest.R

Defines functions mean.spatialDecorrelationMeasure spatialDecorrelation.gmEVario spatialDecorrelation.logratioVariogram spatialDecorrelation.gstatVariogram spatialDecorrelation noSpatCorr.test.matrix noSpatCorr.test.default noSpatCorr.test.data.frame noSpatCorr.test

Documented in mean.spatialDecorrelationMeasure noSpatCorr.test noSpatCorr.test.data.frame noSpatCorr.test.default noSpatCorr.test.matrix spatialDecorrelation spatialDecorrelation.gmEVario spatialDecorrelation.gstatVariogram spatialDecorrelation.logratioVariogram

### a test of lack of spatial correlation
#' Test for lack of spatial correlation
#' 
#' Permutation test for checking lack of spatial correlation.
#'
#' @param Z matrix (or equivalent) of scaled observations
#' @param ... extra arguments for generic functionality
#'
#' @return Produces a test of lack of spatial correlation by means of permutations. The test
#' statistic is based on the smallest eigenvalue of the generalised eigenvalues of the matrices
#' of covariance for short range and for long range.
#' @export
#' @importFrom boot boot
#' @examples
#' data("jura", package="gstat")
#' X = jura.pred[, 1:2]
#' Z = data.frame(compositions::ilr(jura.pred[,-(1:6)]))
#' \dontrun{ 
#' noSpatCorr.test(Z=Z, X=X)
#' # now destroy the spatial structure reshuffling the coordinates:
#' ip = sample(nrow(X))
#' noSpatCorr.test(Z=Z, X=X[ip,]) 
#' }
noSpatCorr.test <- function(Z, ...) UseMethod("noSpatCorr.test", Z)


#' @describeIn noSpatCorr.test  Test for lack of spatial correlation
#' @method noSpatCorr.test data.frame
#' @param X matrix (or equivalent) of sample location coordinates
#' @export
noSpatCorr.test.data.frame <- function(Z, X, ...){
  noSpatCorr.test(as.matrix(Z), X = X, ...)
}

#' @describeIn noSpatCorr.test  Test for lack of spatial correlation, works only for 
#' Spatial objects with a "data" slot
#' @method noSpatCorr.test default
#' @export
noSpatCorr.test.default <- function(Z, ...){
  if(is(Z, "Spatial")){
    coords = sp::coordinates(Z)
    if("data" %in% slotNames(Z)){
      dt = Z@data
      return(noSpatCorr.test(Z=dt, X=coords, ...))
    }
  }
  stop("noSpatCorr.test: default method works only for Spatial***DataFrame objects.")
}


#' @describeIn noSpatCorr.test  Test for lack of spatial correlation
#' @method noSpatCorr.test matrix
#' @param R number of realizations of the Monte Carlo test
#' @param maxlag0 maximum lag distance to consider in the short range covariance
#' @param minlagInf minimum lag distance to consider in the long range covariance
#' @export
noSpatCorr.test.matrix <- function(Z, X, R = 299,
                       maxlag0=0.1*max(as.matrix(dist(X))), 
                       minlagInf=0.25*max(as.matrix(dist(X))),
                       ...){
  X = as.matrix(X)
  nG = ncol(X)
  n = nrow(X)
  X = unclass(idt(X))
    mystat = function(x, idx=1:n){
    X = x[,1:nG]
    Z = as.matrix(x[idx,-(1:nG)])
    ij = expand.grid(i=1:nrow(X), j=1:nrow(X))
    xd = (X[ij$i,]-X[ij$j,])^2 %*% rep(1, ncol(X))
    tk0 = xd<=(maxlag0^2)
    tk1 = xd>=(minlagInf^2)
    C0 = t(Z[ij[tk0,"i"],]-Z[ij[tk0,"j"],]) %*% (Z[ij[tk0,"i"],]-Z[ij[tk0,"j"],]) / (2*sum(tk0))
    C1 = t(Z[ij[tk1,"i"],]-Z[ij[tk1,"j"],]) %*% (Z[ij[tk1,"i"],]-Z[ij[tk1,"j"],]) / (2*sum(tk1))
    #ev = Re(eigen(solve(C0, C1), only.values = T)[[1]])
    #max(ev)/min(ev) + (max(ev)-1)^2
    C1sqrt = gsi.powM(C1, alpha=-0.5)
    ev = eigen(C1sqrt %*% C0 %*% C1sqrt, only.values = TRUE)[[1]]
    ev[length(ev)]
  }
  erg = boot::boot(cbind(X, Z), mystat, R=R, sim="permutation", ...)
  out = list(statistic = erg$t0, p.value = mean(erg$t<erg$t0), 
             method="permutation penalized eigenvalue ratio",
             maxlag0=maxlag0, minlagInf=minlagInf)
  class(out) = "htest"
  return(out)
}




# library("compositions")
# compileme=TRUE
# source("./R/geostats.R")
# turningbands = gsi.TurningBands
# CondSim = gsi.CondTurningBands
# # grid
# r=10
# x = seq(from=-4*r, to=+4*r, by=r/50)
# y = x
# xyGrid = expand.grid(X=x, Y=y)
# V = ilrBase(D=3, method = "balanced")
# #S1 = diag(c(0.5,1,2))
# S = diag(c(4,1)) #,5,1))
# S[1,2]<- S[2,1] <- 1
# M = r*diag(2)
# S = clrvar2ilr(ilrvar2clr(S, V=V))
# 
# #pdf("hello.pdf", width=7, height=7, fam="Times")
# #for(j in 1:3){
# vgram <- setCgram(type=vg.Exp,
#                   nugget=0*S,
#                   sill=S, #(nstru, nvar, nvar)
#                   anisRanges=M     # these are "classical" ranges (i.e. distances)
# )
# 
# plot(vgram) ### looks like we have interpreted M inversely in the plot!!!
# plot(vgram, vdir.up=c(0,1), col=2)
# plot(vgram, vdir.lo=c(1,0), vdir.up=c(0,1), col=2, lwd=3)
# par(plot(vgram, cov=FALSE))
# 
# 
# 
# rs = turningbands(as.matrix(xyGrid),vgram=vgram,nBands=400,nsim=1)
# 
# tk = sample(1:nrow(xyGrid), 1000)
# Xin = as.matrix(xyGrid[tk,])
# plot(Xin)
# Zin = as.matrix(rs[tk,,])
# dim(Zin)
# 
# vg = gsi.EVario2D(X = Xin, Z=Zin, azimuthNr = 1)
# 
# vg2 = gsi.EVario2D(X = Xin, Z=Zin, azimuthNr = 2)
# 
# plot(vg)
# plot(vg2, pch=19, col=2:3, lty=1)
# 
# 
# # Xin = matriz de coordenadas de input
# # Zin = matriz de valores de variables: cbind(z,z)
# CondSim(Xout=as.matrix(xyGrid),Xin,Zin,vgram=vgram,nbands=400,nsim=300) 
# noCorr.test(Xin, Zin, R=99)
# noCorr.test(Xin[sample.int(nrow(Xin), replace=TRUE),], Zin, R=99)  




#### diagonalisation measures
#' Compute diagonalisation measures
#' 
#' Compute one or more diagonalisation measures out of an empirical multivariate variogram.
#'
#' @param vgemp the empirical variogram to qualify
#' @param ... ignored
#'
#' @return an object of a similar nature to `vgemp`, but where the desired quantities are
#' reported for each lag. This can then be plotted or averages be computed.
#' @export
#' 
#' @details The three measures provided are 
#' \describe{
#' \item{absolute deviation from diagonality ("add")}{defined as the sum of all off-diagonal elements
#' of the variogram, possibly squared ($p=2$ if `quadratic=TRUE` the default; otherwise $p=1$)}}
#' \deqn{
#' \zeta(h)=\sum_{k=1}^n\sum_{j\neq k}^n \gamma_{k,j}^p(h)
#' }
#' \describe{
#' \item{relative deviation from diagonality ("rdd")}{comparing the absolute sum of off-diagonal elements  
#' with the sum of the diagonal elements of the variogram, each possibly squared ($p=2$ if `quadratic=TRUE`; 
#' otherwise $p=1$ the default)}}
#' \deqn{
#' \tau(h)=\frac{\sum_{k=1}^n\sum_{j \neq k}^n |\gamma_{k,j}(h)|^p}{\sum_{k=1}^n|\gamma_{k,k}(h)|^p}
#' }
#' \describe{
#' \item{spatial diagonalisation efficiency ("sde")}{is the only one requiring `vgemp0`, because it compares
#' an initial state with a diagonalised state of the variogram system}}
#' \deqn{
#' \kappa(h)=1-
#' \frac{\sum_{k=1}^n\sum_{j \neq k}^n |\gamma_{k,j}(h)|^p}{\sum_{k=1}^n\sum_{j \neq k}^n |\gamma_{(0)k,j}(h)|^p }
#' }
#' 
#' The value of $p$ is controlled by the first value of `method`. That is, the results with `method=c("rdd", "add")` 
#' are not the same as those obtained with `method=c("add", "rdd")`, as in the first case $p=1$ and in the second case $p=2$.
#' 
#'
#' @examples
#' data("jura", package="gstat")
#' X = jura.pred[, 1:2]
#' Z = jura.pred[,-(1:6)]
#' gm1 = make.gmCompositionalGaussianSpatialModel(data=Z, coords=X, V="alr")
#' vg1 = variogram(as.gstat(gm1)) 
#' (r1 = spatialDecorrelation(vg1, method=c("add", "rdd")))
#' plot(r1)
#' mean(r1)
#' require("compositions")
#' pc = princomp(acomp(Z))
#' v = pc$loadings
#' colnames(v)=paste("pc", 1:ncol(v), sep="")
#' gm2 = make.gmCompositionalGaussianSpatialModel(data=Z, coords=X, V=v, prefix="pc")
#' vg2 = variogram(as.gstat(gm2)) 
#' (r2 = spatialDecorrelation(vg2, method=c("add", "rdd")))
#' plot(r2)
#' mean(r2)
#' (r21 = spatialDecorrelation(vg2, vg1, method="sde") )
#' plot(r21)
#' mean(r21)
spatialDecorrelation = function(vgemp, ...) UseMethod("spatialDecorrelation",vgemp)
  

#' @describeIn spatialDecorrelation Compute diagonalisation measures
#' @method spatialDecorrelation gstatVariogram
#' @export
#' @param vgemp0 optionally, a reference variogram (see below; necessary for `method="sde"`)
#' @param method which quantities are desired? one or more of c("rdd", "add", "sde")
#' @param quadratic should the quantities be computed for a variogram or for its square? see below
spatialDecorrelation.gstatVariogram <- function(vgemp, vgemp0=NULL, method="add",quadratic=method[1]!="rdd",...){
 if(length(method)==1){  
  if(method=="add"){
    if(quadratic) vgemp$gamma = vgemp$gamma^2
    aux = split(vgemp, vgemp$id)
    erg = aux[[1]]
    erg$gamma = 0*erg$gamma
    tk = grep(".", names(aux), fixed=TRUE)
    for(o in tk) erg$gamma = erg$gamma + 2*abs(aux[[o]]$gamma)
   }else if(method=="rdd"){
     if(quadratic) vgemp$gamma = vgemp$gamma^2
     aux = split(vgemp, vgemp$id)
     erg = aux[[1]]
     erg$gamma = 0*erg$gamma
     ergdenom = erg$gamma
     tk = grep(".", names(aux), fixed=TRUE)
     for(o in tk) erg$gamma = erg$gamma + 2*abs(aux[[o]]$gamma)
     for(o in (1:length(aux))[-tk]) ergdenom = ergdenom + abs(aux[[o]]$gamma)
     erg$gamma = erg$gamma/ergdenom 
  }else if(method=="sde"){
    if(is.null(vgemp0)) stop("spatialDecorrelation: for method 'sde' a variogram for an initial configuration vgemp0 is needed!")
    aux = spatialDecorrelation(vgemp, method="add", quadratic = quadratic)
    aux2 = spatialDecorrelation(vgemp0, method="add", quadratic = quadratic)
    erg = aux
    erg$gamma = 1-aux$gamma/aux2$gamma
  }else stop("spatialDecorrelation: unkonw method! choose one of 'add', 'rdd' or 'sde'")
  erg$id =  factor(erg$id[, drop=T], labels=method)
  class(erg) = unique(c("spatialDecorrelationMeasure", class(erg) ))
  return(erg)
 }else{
   aux = lapply(method , function(m){
     spatialDecorrelation(vgemp=vgemp, vgemp0=vgemp0, method=m,quadratic=quadratic,...)
   })
   erg = aux[[1]]
   for(i in 2:length(aux)) erg = rbind(erg, aux[[i]])
   class(erg) = unique(c("spatialDecorrelationMeasure", class(erg) ))
   return(erg)
 }  
} 

#' @describeIn spatialDecorrelation Compute diagonalisation measures
#' @method spatialDecorrelation logratioVariogram
#' @export
spatialDecorrelation.logratioVariogram <- function(vgemp,vgemp0=NULL, method="add",...){
  stop("spatialDecorrelation meaningless for logratioVariogram")
} 

#' @describeIn spatialDecorrelation Compute diagonalisation measures
#' @method spatialDecorrelation gmEVario
#' @export
spatialDecorrelation.gmEVario <- function(vgemp,vgemp0=NULL, method="add",...){
  stop("not yet implemented")
} 



#' Average measures of spatial decorrelation
#' 
#' Compute average measres of spatial decorrelation out of the result of a call 
#' to [spatialDecorrelation()]
#'
#' @param x the outcome of a call to [spatialDecorrelation()]
#' @param ... further arguments to mean
#'
#' @return a mean for each measure available on `x`, i.e. this can be a vector.
#' The output is named.
#' @export
#' @seealso [spatialDecorrelation()] for an example
mean.spatialDecorrelationMeasure = function(x, ...){
  sapply(split(x$gamma, as.factor(x$id)), mean, ...)
} 

Try the gmGeostats package in your browser

Any scripts or data that you put into this service are public.

gmGeostats documentation built on April 18, 2023, 5:08 p.m.