简体   繁体   中英

Is it possible to analyse a spatial point pattern given another, underlying, spatial point pattern in R

I want to analyse the type of spatial pattern shown by an animal (ie random, clustered, uniform) taking into consideration the underlying spatial pattern of it's available habitat. The animals in question roost in trees, so a standard analysis of the animal spp will always show a clustered distribution (ie clustering around trees), but I want to test whether there is clustering between trees vs whether they distribute randomly throughout trees. To provide a visual, I want to be able to differentiate between the following scenarios in the image:

https://imgur.com/a/iE3nAoh (image not allowed because I'm new to stack overflow, but it's available through the link)

Here is a reproducible data frame. The scenario here is of uniform habitat (25 areas of habitat) and uniform animals (16 animals per habitat):

library(spatstat)
data <- data.frame(matrix(ncol = 4, nrow = 25))
x <- c("habitat", "x", "y", "animalcount")
colnames(data) <- x
data$habitat <- 1:25
data$x <- seq(from=2, to=20, by=4)
data$y[1:5] <- 2
data$y[6:10] <- 6
data$y[11:15] <- 10
data$y[16:20] <- 14
data$y[21:25] <- 18
data$animalcount <- 16

Set up conditions for the spatial analysis:

plot.win <- owin(c(0,20), c(0,20)) # set the plot window as 20x20m
nS <- 499 # number of simulations
cd <- 5 # cluster distance
ed <- 50 # envelope distance
incr.dist <- 0.5 # increment distance for envelopes

Create the point pattern for the habitat:

habitat <- ppp(x = data$x, y = data$y, window = plot.win)

Create the point pattern for the animals. To do this, first make a new dataframe with repeated rows for the number in animal count, so that points are individual animals. Jitter x/y so that x/y coordinates are not exactly the same:

data <-data[which(data$animalcount>0),]
duplicate_rows <- function(habitat, x, y, animalcount) {
  expanded <- paste0("animal-", 1:animalcount)
  repeated_rows <- data.frame("habitat" = habitat, "x" = x, "y" = y, "animalcount" = expanded)
  repeated_rows
}
expanded_rows <- Map(f = duplicate_rows, data$habitat, data$x, data$y, data$animalcount)
animal_data <- do.call(rbind, expanded_rows)
animal_data$xan <- jitter(animal_data$x)
animal_data$yan <- jitter(animal_data$y)

animal <- ppp(x = animal_data$xan, y = animal_data$yan, window = plot.win)

Now test Complete Spatial Randomness of animals regardless of habitat. This should come out as clustered:

an.csr <- envelope(animal, Kest, nsims = nS, savepatterns = TRUE, r = seq(0, ed, incr.dist), correction=c("Ripley"), verbose = FALSE) #CSR fit and determine the number of simulations
an.dclf <- dclf.test(an.csr, rinterval = c(0,cd), verbose = FALSE) #calculate the summary statistics of the CSR null model fit (dclf.test)
plot(an.csr, sqrt(./pi)-r~r, ylab="L(r)-r", xlab="r (meters)", xlim=c(0,ed), legend="NULL", main=paste("Animal - CSR", sep = "")) #plot 0-centered fit with the confidence bounds 
clarkevans(animal)[2] #R > 1 suggests ordering, < 1 suggests clustering
clarkevans.test(animal, "Donnelly")$p

Now test Complete Spatial Randomness of animals, given the available habitat. This should come out not clustered. But simply adding habitat as a covariate clearly isn't the appropriate way to do it:

an.csr <- envelope(animal, covariates = animal_data[,2:3], Kest, nsims = nS, savepatterns = TRUE, r = seq(0, ed, incr.dist), correction=c("Ripley"), verbose = FALSE)
an.dclf <- dclf.test(an.csr, rinterval = c(0,cd), verbose = FALSE) 
plot(an.csr, sqrt(./pi)-r~r, ylab="L(r)-r", xlab="r (meters)", xlim=c(0,ed), legend="NULL", main=paste("Animal - CSR", sep = "")) 
clarkevans(animal)[2] 
clarkevans.test(animal, "Donnelly")$p

I also tried running the test of Complete Spatial Randomness on a fitted Point Process Model, where the animal point pattern could be predicted by x&y, but this also did not change outcomes:

animalppm<-ppm(animal~x+y)
an.csr <- envelope(animalppm, Kest, nsims = nS, savepatterns = TRUE, r = seq(0, ed, incr.dist), correction=c("Ripley"), verbose = FALSE) 
an.dclf <- dclf.test(an.csr, rinterval = c(0,cd), verbose = FALSE) 
plot(an.csr, sqrt(./pi)-r~r, ylab="L(r)-r", xlab="r (meters)", xlim=c(0,ed), legend="NULL", main=paste("Animal - CSR", sep = "")) 
clarkevans(animalppm)[2] #R > 1 suggests ordering, < 1 suggests clustering
clarkevans.test(animalppm, "Donnelly")$p

From there I would run tests of aggregation models, but the logic of adding the second point pattern should be similar.

I would appreciate any suggestions on ways to deal with this. I cannot think of an effective way to google this, and am coming up short on clever coding solutions in R. Thanks in advance!

You can model the intensity as depending on the distance to the habitat pattern. Here is a simple example where the animals follow a Poisson point process with intensity function which decays log-linearly with distance to the habitat:

library(spatstat)

data <- expand.grid(x = seq(2, 18, by=4), y = seq(2, 18, by=4))
data$animalcount <- 16

plot.win <- owin(c(0,20), c(0,20)) # set the plot window as 20x20m

habitat <- ppp(x = data$x, y = data$y, window = plot.win)

d <- distmap(habitat)
plot(d)

lam <- exp(3-2*d)
plot(lam)

animal <- rpoispp(lam)
plot(animal)

fit <- ppm(animal ~ d)
fit
#> Nonstationary Poisson process
#> 
#> Log intensity:  ~d
#> 
#> Fitted trend coefficients:
#> (Intercept)           d 
#>    2.952048   -1.974381 
#> 
#>              Estimate       S.E.   CI95.lo   CI95.hi Ztest      Zval
#> (Intercept)  2.952048 0.07265533  2.809646  3.094450   ***  40.63085
#> d           -1.974381 0.07055831 -2.112673 -1.836089   *** -27.98226

Taking the underlying non-homogeneous intensity into account there is no sign of departure from the Poisson model in the (inhomogeneous) K-function:

plot(Kinhom(animal, lambda = fit))
#> Warning: The behaviour of Kinhom when lambda is a ppm object has changed
#> (in spatstat 1.37-0 and later). See help(Kinhom)

You don't have to have simple log-linear dependence on distance. You could also make a threshold model where you have one intensity with eg distance 1 of the habitat and another intensity outside this distance. You can make all kinds of derived covariates from eg the distance for use in your model.

If animals is the point pattern of animals, and trees is the point pattern of trees (both objects of class "ppp" in spatstat) then you could do

d <- distfun(trees)
f <- rhohat(animals, d)
plot(f)

to get an idea of how the concentration of animals depends on distance to nearest tree. You can use

berman.test(animals, d)

to perform a hypothesis test of dependence on the trees.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM