Determinando a distribuição espacial a partir da Distribuição do vizinho mais próximo

Quando a gente estava medindo as distâncias ao vizinho mais próximo aqui, se a gente olhar a distribuição desses, a gente vai ver algo interessante aparecer.

Primeiro, vamos transformar em funções aquelas operações.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
##Distância entre pontos
distancia <- function(x1,y1,x2,y2){
    sqrt((x2 - x1)^2 + (y2 - y1)^2)
}
 
#Calcula distancias do vizinho mais próximo
calcula_r<- function(x,y){
    r <- vector()
    nn <- vector()
    d <- vector()
    for (i in 1:100) {
        d <- distancia(x[i],y[i],x,y)
        r[i] <- min(d[-i])
    }
    return(r)
}

O que nos interessa, é calcular a média das distâncias ao vizinho mais próximo.

1
2
3
4
5
6
7
n<-1000
dist_vmp<-vector()
 
for(i in 1:n){
    r<-calcula_r(runif(100),runif(100))
    dist_vmp[i]<-mean(r)
}

Fazemos isso muitas vezes, uma mil, e podemos dar uma olhada em como fica a distribuição dessas mil médias. Veja que estamos gerando uma distribuição de pontos ao acaso no espaço, e para cada um desses conjuntos, a gente calcula a média dos vizinhos mais próximos.

01

Veja que é assim que fica a média de vizinhos mais próximos, quando os pontos estão distribuídos ao acaso no espaço. Veja que se a gente pegar outro exemplo, e vamos ilustrar os pontos aqui.

02

Em relação a nossa distribuição, veja onde fica o média de vizinhos mais próximos.

03

Bem, até aqui, nada de novo, a gente sempre está gerando os pontos ao acaso, então temos essa distribuição média. Agora vamos considerar um segundo caso.

04

Agora nos temos os pontos agregados em alguns pontos. Agregações na natureza ocorrem por muitos motivos, pode ser mais seguro ficar perto de outros pontinhos, ali pode ser o local onde os melhores recursos estão estocados, enfim várias coisas ponde acontecer. Mas isso tem algum impacto na média do vizinhos mais próximo? Bem, todo mundo vai tender a estar mais pertinho, e assim teremos uma média mais baixa. Para esse exemplo, podemos calcular a média e comparar com a distribuição dos mil casos aleatórios.

05

E o que acontece é exatamente isso, o valor de média fica bem menor, bem antes da distribuição, já que todo mundo mais pertinho que o acaso. Porque algum motivo atrai todo os pontinho para o mesmo lugar.

Agora existe outra possibilidade, que é algo como, melhor sozinho do que acompanhado, ou seja, pense num caso de competição extrema, então a gente tenta ficar o mais longe possível de outros competidores.

07

Que gera um padrão mais ou menos como o acima. Agora o que vai acontecer com a média de distância do vizinho mais próximo? Agora ela fica um valor alto, porque sempre temos valores altos.

08

O que estamos vendo aqui? Baseado na média da distancia do vizinho mais próximo, podemo ter uma noção da distribuição espacial dos pontos, sabendo se ela é aleatória ou não, e não sendo aleatória, por esse valor, temos ainda uma noção se tudo está agregado ou espaçado. Sendo que existe um gradiente entre agregado e espaço, e o aleatório está no meio desse gradiente.

09

Teoricamente, a gente nem precisa calcular a distribuição aleatória dos pontos, porque temos uma expectativa para esse valor, que é

E(r)=\frac{\sqrt{p}}{2}

Onde r é a média das distancias do vizinho mais próximo, E é de esperança, a média para distribuições e p é a densidade de pontos, quantos pontos temos por unidade de espaço.

Se a gente olhar a média da nossa simulação

> mean(dist_vmp) [1] 0.05220953

E sabendo que temos 100 pontos, para uma área de 10000 cm2, área aqui é uma unidade meio vaga ja que estamos numa simulação.

> E_r<-sqrt(100/10000)/2 > E_r [1] 0.05

Mas chegamos a um valor bem próximo de média. E como temos uma expectativa, isso facilita a tentar interpretar esse valor como uma razão, se dividirmos o valor que encontramos por esse valor esperado, temos que:

Nos casos de distribuição aleatória, ele estará próximo de 1

> r_ale/E_r [1] 1.111665

Nos casos de agregamento, ele estára abaixo de 1

> r_agre/E_r [1] 0.4468558

E no caso de distribuição uniforme, ele será maior que 1

> r_uni/E_r [1] 1.810889

Mas apesar de tudo essa técnica leva a um outro problema, que é o seguinte. Para conseguirmos ter uma ideia do que é esperado para o local, precisamos saber a densidade de pontos do local, mas isso a gente só sabe com certeza, se tivermos certeza que estamos vendo todos os pontos do local, e como já vimos varias vezes, nossas contagens são normalmente tudo menos precisa. Logo isso é um problema para ter um valor esperado para r, o que dificulta bastante o uso desse método. Mas na teoria ele funciona bem.

Bem é isso ai, brincando mais um pouquinho com as distancias do vizinho mais próximo, o script vai estar la no repositório recologia, e se eu escrevi alguma bobeira, algo errado, deixe um comentário corrigindo ou mande um e-mail.

Referência:
Michael J Crawley 2007 – R Book 2nd. Editora Wiley 1072pp .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
##Distância entre pontos
distancia <- function(x1,y1,x2,y2){
    sqrt((x2 - x1)^2 + (y2 - y1)^2)
}
 
#Calcula distancias do vizinho mais próximo
calcula_r<- function(x,y){
    r <- vector()
    nn <- vector()
    d <- vector()
    for (i in 1:100) {
        d <- distancia(x[i],y[i],x,y)
        r[i] <- min(d[-i])
    }
    return(r)
}
 
##Simular média do vizinho mais próximo
n<-1000
dist_vmp<-vector()
 
for(i in 1:n){
    r<-calcula_r(runif(100),runif(100))
    dist_vmp[i]<-mean(r)
}
 
##Resultado da simulação
hist(dist_vmp,main="Distribuição de médias do vizinho mais próximo")
 
##Avaliando alguns casos:
##Caso aléatorio
x<-runif(100)
y<-runif(100)
 
plot(x,y)
 
r_ale<-mean(calcula_r(x,y))
hist(dist_vmp)
abline(v=r_ale,lwd=2,col="blue",lty=2)
legend("topright",lwd=2,col="blue",lty=2,legend="Aleatório",bty="n")
 
##Caso Agregado
x<-c(rnorm(50,0.25,0.05),rnorm(50,0.6,0.1))
y<-c(rnorm(50,0.25,0.1),rnorm(50,0.7,0.05))
 
plot(x,y)
 
r_agre<-mean(calcula_r(x,y))
hist(dist_vmp,xlim=c(min(dist_vmp,r_agre),max(dist_vmp)))
abline(v=r_agre,lwd=2,col="red",lty=2)
legend("top",lwd=2,col="red",lty=2,legend="Agregado",bty="n")
 
##Caso Uniforme
x<-rep(seq(0.01,0.99,length=10),10)+runif(100,-0.002,0.05)
y<-rep(seq(0.01,0.99,length=10),each=10)+runif(100,-0.002,0.05)
 
plot(x,y)
 
r_uni<-mean(calcula_r(x,y))
hist(dist_vmp,xlim=c(min(dist_vmp),max(dist_vmp,r_uni)))
abline(v=r_uni,lwd=2,col="green",lty=2)
legend("top",lwd=2,col="green",lty=2,legend="Uniforme",bty="n")
 
hist(dist_vmp,xlim=c(min(dist_vmp,r_agre),max(dist_vmp,r_uni)))
abline(v=r_ale,lwd=2,col="blue",lty=2)
abline(v=r_agre,lwd=2,col="red",lty=2)
abline(v=r_uni,lwd=2,col="green",lty=2)
legend("topright",lwd=2,col=c("blue","red","green"),lty=2,legend=c("Aleatório","Agregado","Uniforme"),bty="n")
 
##Observado para uma distribuição ao acaso
mean(dist_vmp)
 
##Valor Predito
E_r<-sqrt(100/10000)/2
E_r
 
#Razão observado por esperado
r_ale/E_r
r_agre/E_r
r_uni/E_r

Distância até o vizinho mais próximo.

A gente ja falou de point process aqui, agora vamos ver como é a distribuição do vizinho mais próximo, e o efeito de borda que podemos ter nele, isso é meio confuso, mas vamos la.

Suponha que nos temos o problema de desenhar linhas para unir os pares de vizinhos mais próximos em um dado conjunto de pontos (x,y) que estão mapeados em duas dimensões.

Então esse é o nosso conjunto:

01

Nos precisamos de três passos.

  • Calcular a distância para o vizinho mais próximo
  • Identificar o vizinho mais próximo de cada ponto
  • usar essas distâncias minimas para identificar todos os vizinhos mais pŕoximos

Para o primeiro passo, é só calcular a distância, usando o bom e velho triângulo retângulo.

triganguloretangulo

Então a gente implementa a fórmula d=\sqrt{(y_2-y_1)^2+(x_2-x_1)^2}

1
2
3
distancia <- function(x1,y1,x2,y2){
    sqrt((x2 - x1)^2 + (y2 - y1)^2)
}

Agora nos percorremos o pontos e calculamos um vetor de distâncias, que vamos chamar de d. Ai desse vetor a gente pega a menor distância, tirando o i porque não adianta a distância de um ponto para ele mesmo, e guardamos o índice também do ponto mais próximo.

1
2
3
4
5
6
7
for (i in 1:100) {
    for (j in 1:100){
        d[j] <- distancia(x[i],y[i],x[j],y[j])
    }
    r[i] <- min(d[-i])
    nn[i] <- which(d==r[i])
}

Agora podemos colocar no gráfico, uma linha unindo os pontos mais próximos.

02

Veja que alguns pontos tem a linha de mais próximo sobrepostos. Agora vamos identificar quem está mais próximo da borda. A borda inferior e da esquerda são zero, as bordas superiores e da direta são 1, a gente pode calcular a distância para todos os pontos, vendo o menor entre todas as bordas.

borda <- pmin(x,y,dist_borda_superior,dist_borda_direita) Veja que isso funciona, porque o valor mínimo é zero, ai temos a distancia para as bordas superiores e direta, e pegamos o valor mínimo desses conjuntos, como temos um quadrado, não tem porque pegar uma distância diagonal. Agora podemos ver quantos desses valores são menores que a distância para o vizinho mais próximo.

> sum(borda

Podemos identificar esses caras no mapa

03

Agora olha o que acontece com esses valores, quando vemos a média deles com e sem esses indivíduos da borda.

04

Comumente, uma amostra é parte de um todo, então existe mais pontos, fora dessas bordas que não vemos, se pensarmos assim, veja que alguns pontos estão longe de outros pontos meramente porque não podemos ver o ponto mais próximo dele, que está fora do nosso campo de visão, fora da borda. Então eles terem recebido uma distância maior tem do vizinho mais próximo tem haver com isso na verdade. Veja que se identificamos esses caras perto demais da borda, podemos desconfiar deles, e se retiramos eles, a gente diminui a média de distâncias do vizinho mais próximo. Mas perdemos um pouco de pontos amostrados fazendo isso.

Agora pensando numa amostragem real, esse efeito pode ser muito maior se a gente usar um retângulos como área de amostra, o famoso transecto. Mas pode ser minimizado usando um circulo, que é mais difícil de implementar no campo. Então isso é algo a se levar em conta num delineamento, quando o espaço é importante, a distribuição espacial, a localização das amostras.

Bem é isso ai, o script vai estar la no repositório recologia, e se eu escrevi alguma bobeira, algo errado, deixe um comentário corrigindo ou mande um e-mail.

Referência:
Michael J Crawley 2007 – R Book 2nd. Editora Wiley 1072pp .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
set.seed(2)
 
##Distribuição de pontos aleatórios
x <- runif(100)
y <- runif(100)
 
##Num mapa
plot(x,y,pch=19,col="black",main="Mapa")
 
##Distância entre pontos
distancia <- function(x1,y1,x2,y2){
    sqrt((x2 - x1)^2 + (y2 - y1)^2)
}
 
##Menor Distância para cada ponto
 
##Vetor para guardar a menor distância
r <- vector()
##Vetor para guardar o indice do ponto mais próximo
nn <- vector()
#Vetor auxiliar para guardar todas as distâncias
d <- vector()
 
##Para cada ponto i
for (i in 1:100) {
    ##Calcular a distancia dele até o ponto j
    for (j in 1:100){
        d[j] <- distancia(x[i],y[i],x[j],y[j])
    }
    ##Qual a menor distância? Note que tiramos o i, porque a
    ##distância de um ponto pra ele mesmo não interessa, é 0
    ##Anotamos a distância
    r[i] <- min(d[-i])
    ##E o indice do ponto correspondente
    nn[i] <- which(d==r[i])
}
 
##Desenhando uma linha até o ponto mais próximo
plot(x,y,pch=19,col="black")
for (i in 1:100){
    lines(c(x[i],x[nn[i]]),c(y[i],y[nn[i]]),col="red",lty=3,lwd=2)
}
 
##Descobrindo quem está mais próximo da borda do que do vizinho mais próximo:
 
##bordas
dist_borda_superior <- 1-y
dist_borda_direita <- 1-x
 
##Distância para a borda
borda <- pmin(x,y,dist_borda_superior,dist_borda_direita)
 
##Quantos pontos estão mais próximos da borda
##Do que do vizinho mais próximo
sum(borda<r)
 
##
plot(x,y,pch=19)
indice <- which(borda<r)
points(x[indice],y[indice],col="red",cex=1.5,lwd=2)
 
##
layout(matrix(1:4,ncol=2,nrow=2))
hist(borda,xlim=c(0,0.5),ylim=c(0,20),breaks=seq(0,0.5,length.out = 20),main="Distância para borda")
hist(borda[-indice],xlim=c(0,0.5),ylim=c(0,20),breaks=seq(0,0.5,length.out = 20),main="Sem efeito de borda")
hist(r,xlim=c(0,0.15),ylim=c(0,20),breaks=seq(0,0.15,length.out = 20),main=paste("Vizinho Mais Próximo\n Média:",round(mean(r),4)))
hist(r[-indice],xlim=c(0,0.15),ylim=c(0,20),breaks=seq(0,0.15,length.out = 20),
     main=paste("Sem efeito de borda\n Média:",round(mean(r[-indice]),4)))