Dada uma amostra grande (~ 1 milhão) de pontos desigualmente distribuídos - é possível gerar uma grade irregular (em tamanho, mas também pode ter uma forma irregular se for possível?) Que conterá uma quantidade mínima especificada de n pontos?
É menos importante para mim se as 'células' geradas dessa grade contenham exatamente n número de pontos ou pelo menos n pontos.
Estou ciente de soluções como genvecgrid no ArcGIS ou Create Grid Layer no QGIS / mmgis, no entanto, todas elas criarão grades regulares que resultarão em uma saída com células vazias (problema menor - eu poderia simplesmente descartá-las) ou células com contagem de pontos menor que n (problema maior, pois eu precisaria de uma solução para agregar essas células, provavelmente usando algumas ferramentas daqui ?).
Estou pesquisando sem sucesso e estou aberto a soluções comerciais (ArcGIS e extensões) ou gratuitas (Python, PostGIS, R).
fonte
Respostas:
Vejo que MerseyViking recomendou um quadtree . Eu sugeriria a mesma coisa e, para explicar, aqui está o código e um exemplo. O código está escrito,
R
mas deve portar facilmente para, por exemplo, Python.A idéia é notavelmente simples: divida os pontos aproximadamente ao meio na direção x, depois divida recursivamente as duas metades ao longo da direção y, alternando as direções em cada nível, até que não seja mais necessária a divisão.
Como a intenção é disfarçar a localização real dos pontos, é útil introduzir alguma aleatoriedade nas divisões . Uma maneira rápida e simples de fazer isso é dividir em um conjunto de quantis uma pequena quantidade aleatória de 50%. Dessa maneira (a) é altamente improvável que os valores de divisão coincidam com as coordenadas dos dados, de modo que os pontos caem exclusivamente nos quadrantes criados pela partição e (b) será impossível reconstruir precisamente as coordenadas dos pontos a partir da quadtree.
Como a intenção é manter uma quantidade mínima
k
de nós dentro de cada folha de quadtree, implementamos uma forma restrita de quadtree. Ele suportará (1) pontos de agrupamento em grupos que possuem entrek
e 2 *k
-1 elementos cada e (2) mapear os quadrantes.Esse
R
código cria uma árvore de nós e folhas de terminal, distinguindo-os por classe. A rotulagem da classe agiliza o pós-processamento, como plotagem, mostrada abaixo. O código usa valores numéricos para os IDs. Isso funciona até profundidades de 52 na árvore (usando dobras; se números inteiros longos não assinados forem usados, a profundidade máxima será 32). Para árvores mais profundas (que são altamente improváveis em qualquer aplicação, porque pelo menosk
* 2 ^ 52 pontos estariam envolvidos), os IDs teriam que ser cadeias de caracteres.Observe que o design recursivo de dividir e conquistar deste algoritmo (e, conseqüentemente, da maioria dos algoritmos de pós-processamento) significa que o tempo necessário é O (m) e o uso de RAM é O (n) onde
m
é o número de células en
é o número de pontos.m
é proporcional aon
dividido pelos pontos mínimos por célula,k
. Isso é útil para estimar os tempos de computação. Por exemplo, se levar 13 segundos para particionar n = 10 ^ 6 pontos em células de 50-99 pontos (k = 50), m = 10 ^ 6/50 = 20000. Se você desejar particionar para 5-9 pontos por célula (k = 5), m é 10 vezes maior, então o tempo sobe para cerca de 130 segundos. (Como o processo de dividir um conjunto de coordenadas em torno de seus médios fica mais rápido à medida que as células diminuem, o tempo real era de apenas 90 segundos.) Para percorrer todo o caminho de k = 1 ponto por célula, levará cerca de seis vezes mais ainda, ou nove minutos, e podemos esperar que o código seja realmente um pouco mais rápido que isso.Antes de prosseguir, vamos gerar dados interessantes com espaçamento irregular e criar sua quadtree restrita (tempo decorrido de 0,29 segundos):
Aqui está o código para produzir esses gráficos. Ele explora
R
o polimorfismo:points.quadtree
será chamado sempre que apoints
função for aplicada a umquadtree
objeto, por exemplo. O poder disso é evidente na extrema simplicidade da função de colorir os pontos de acordo com o identificador de cluster:A plotagem da grade em si é um pouco mais complicada, pois requer recortes repetidos dos limites usados para o particionamento de quadtree, mas a mesma abordagem recursiva é simples e elegante. Use uma variante para construir representações poligonais dos quadrantes, se desejado.
Como outro exemplo, gerei 1.000.000 de pontos e os particionei em grupos de 5 a 9 cada. O tempo foi de 91,7 segundos.
Como um exemplo de como interagir com um GIS , vamos escrever todas as células quadtree como um arquivo de forma de polígono usando a
shapefiles
biblioteca. O código emula as rotinas de recorte delines.quadtree
, mas desta vez ele precisa gerar descrições vetoriais das células. Eles são produzidos como quadros de dados para uso com ashapefiles
biblioteca.Os pontos em si podem ser lidos diretamente usando
read.shp
ou importando um arquivo de dados de coordenadas (x, y).Exemplo de uso:
(Use qualquer extensão desejada para exibir
xylim
aqui em uma sub-região ou expandir o mapeamento para uma região maior; esse código é padronizado na extensão dos pontos.)Isso por si só é suficiente: uma junção espacial desses polígonos aos pontos originais identificará os agrupamentos. Uma vez identificadas, as operações de "resumo" do banco de dados geram estatísticas resumidas dos pontos dentro de cada célula.
fonte
shapefiles
pacote ou pode exportar (x, y) coordenadas no texto ASCII e lê-las comread.table
. (2) eu recomendo escrever deqt
duas formas: primeiro, como um shapefile de ponto paraxy
onde osid
campos são incluídos como identificadores de cluster; segundo, onde os segmentos de linha plotados porlines.quadtree
são gravados como um arquivo de forma polilinha (ou onde o processamento análogo grava as células como um arquivo de forma poligonal). Isso é tão simples quanto modificarlines.quadtree.leaf
a saídaxylim
como um retângulo. (Veja as edições.)quad
: (1) inicializarid=1
; (2) mudeid/2
paraid*2
nalower=
linha; (3) faça uma alteração semelhante àid*2+1
daupper=
linha. (Vou editar minha resposta para refletir isso.) Isso também deve cuidar do cálculo da área: dependendo do seu GIS, todas as áreas serão positivas ou todas serão negativas. Se todas forem negativas, inverta as listas parax
e paray
dentrocell.quadtree.leaf
.Veja se este algoritmo fornece anonimato suficiente para sua amostra de dados:
Por exemplo, se o limite mínimo for 3:
fonte
Da mesma forma que a interessante solução de Paulo, que tal usar um algoritmo de subdivisão de quatro árvores?
Defina a profundidade que você deseja que o quadtree vá. Você também pode ter um número mínimo ou máximo de pontos por célula, para que alguns nós sejam mais profundos / menores que outros.
Subdivida seu mundo, descartando nós vazios. Enxágue e repita até que os critérios sejam atendidos.
fonte
Outra abordagem é criar uma grade muito fina e usar o algoritmo max-p. http://pysal.readthedocs.org/en/v1.7/library/region/maxp.html
fonte