Étant donné un large échantillon (~ 1 million) de points inégalement répartis - est-il possible de générer une grille irrégulière (en taille, mais pourrait également être de forme irrégulière si cela est possible?) Qui contiendra la quantité minimale spécifiée de n points?
Cela a moins d'importance pour moi si les «cellules» générées d'une telle grille contiennent exactement n nombre de points ou au moins n points.
Je connais des solutions comme genvecgrid dans ArcGIS ou Create Grid Layer dans QGIS / mmgis, mais elles créeront toutes des grilles régulières qui se traduiront par une sortie avec des cellules vides (problème plus petit - je pourrais simplement les éliminer) ou des cellules avec un nombre de points moins que n (plus gros problème car j'aurais besoin d'une solution pour agréger ces cellules, en utilisant probablement des outils d' ici ?).
Je suis allé sur Google en vain et je suis ouvert aux solutions commerciales (ArcGIS et extensions) ou gratuites (Python, PostGIS, R).
la source
Réponses:
Je vois que MerseyViking a recommandé un quadtree . J'allais suggérer la même chose et pour l'expliquer, voici le code et un exemple. Le code est écrit
R
mais doit facilement être porté sur, par exemple, Python.L'idée est remarquablement simple: diviser les points environ en deux dans la direction x, puis diviser récursivement les deux moitiés le long de la direction y, en alternant les directions à chaque niveau, jusqu'à ce que plus aucune division ne soit souhaitée.
Étant donné que l'intention est de masquer les emplacements réels des points, il est utile d'introduire un certain caractère aléatoire dans les divisions . Un moyen simple et rapide de le faire est de diviser à un ensemble de quantiles une petite quantité aléatoire à partir de 50%. De cette façon (a) les valeurs de division sont très peu susceptibles de coïncider avec les coordonnées des données, de sorte que les points tomberont uniquement dans les quadrants créés par le partitionnement, et (b) les coordonnées des points seront impossibles à reconstruire avec précision à partir du quadtree.
Parce que l'intention est de maintenir une quantité minimale
k
de nœuds dans chaque feuille de quadtree, nous implémentons une forme restreinte de quadtree. Il prendra en charge (1) les points de regroupement en groupes ayant entrek
et 2 *k
-1 éléments chacun et (2) la cartographie des quadrants.Ce
R
code crée un arbre de nœuds et de feuilles terminales, les distinguant par classe. L'étiquetage de classe accélère le post-traitement tel que le traçage, illustré ci-dessous. Le code utilise des valeurs numériques pour les identifiants. Cela fonctionne jusqu'à des profondeurs de 52 dans l'arborescence (en utilisant des doubles; si des entiers longs non signés sont utilisés, la profondeur maximale est de 32). Pour les arbres plus profonds (qui sont très peu probables dans n'importe quelle application, car au moinsk
* 2 ^ 52 points seraient impliqués), les identifiants devraient être des chaînes.Notez que la conception récursive de division et de conquête de cet algorithme (et, par conséquent, de la plupart des algorithmes de post-traitement) signifie que l'exigence de temps est O (m) et que l'utilisation de la RAM est O (n) où
m
est le nombre de cellules etn
est le nombre de points.m
est proportionnel àn
divisé par le nombre minimum de points par cellule,k
. Ceci est utile pour estimer les temps de calcul. Par exemple, s'il faut 13 secondes pour partitionner n = 10 ^ 6 points en cellules de 50-99 points (k = 50), m = 10 ^ 6/50 = 20000. Si vous voulez plutôt partitionner en 5-9 points par cellule (k = 5), m est 10 fois plus grand, donc le chronométrage monte à environ 130 secondes. (Parce que le processus de division d'un ensemble de coordonnées autour de leur milieu devient plus rapide à mesure que les cellules deviennent plus petites, le temps réel n'était que de 90 secondes.) Pour aller jusqu'à k = 1 point par cellule, cela prendra environ six fois plus longtemps encore, ou neuf minutes, et nous pouvons nous attendre à ce que le code soit un peu plus rapide que cela.Avant d'aller plus loin, générons des données intéressantes espacées de manière irrégulière et créons leur quadtree restreint (temps écoulé de 0,29 seconde):
Voici le code pour produire ces tracés. Il exploite
R
le polymorphisme de:points.quadtree
sera appelé chaque fois que lapoints
fonction est appliquée à unquadtree
objet, par exemple. La puissance de ceci est évidente dans l'extrême simplicité de la fonction pour colorer les points selon leur identifiant de cluster:Le tracé de la grille elle-même est un peu plus délicat car il nécessite un écrêtage répété des seuils utilisés pour le partitionnement en quadtree, mais la même approche récursive est simple et élégante. Utilisez une variante pour construire des représentations polygonales des quadrants si vous le souhaitez.
Comme autre exemple, j'ai généré 1 000 000 de points et les ai répartis en groupes de 5 à 9 chacun. Le chronométrage était de 91,7 secondes.
Pour illustrer comment interagir avec un SIG , écrivons toutes les cellules quadtree sous forme de fichier de formes polygonales à l'aide de la
shapefiles
bibliothèque. Le code émule les routines d'écrêtage delines.quadtree
, mais cette fois il doit générer des descriptions vectorielles des cellules. Ils sont sortis sous forme de trames de données à utiliser avec lashapefiles
bibliothèque.Les points eux-mêmes peuvent être lus directement en utilisant
read.shp
ou en important un fichier de données de coordonnées (x, y).Exemple d'utilisation:
(Utilisez l'étendue souhaitée
xylim
pour ouvrir une fenêtre dans une sous-région ou étendre le mappage à une région plus grande; ce code correspond par défaut à l'étendue des points.)Cela suffit à lui seul: une jonction spatiale de ces polygones aux points d'origine identifiera les clusters. Une fois identifiées, les opérations de "résumé" de la base de données généreront des statistiques récapitulatives des points dans chaque cellule.
la source
shapefiles
paquet ou bien vous pouvez exporter les coordonnées (x, y) en texte ASCII et les lire avecread.table
. (2) Je recommande d'écrireqt
sous deux formes: premièrement, en tant que fichier de formes ponctuel pour indiquerxy
où lesid
champs sont inclus en tant qu'identificateurs de cluster; deuxièmement, lorsque les segments de ligne tracés parlines.quadtree
sont écrits sous forme de fichier de formes polyligne (ou lorsque le traitement analogue écrit les cellules sous forme de fichier de formes polygonales). C'est aussi simple que de modifierlines.quadtree.leaf
pour produirexylim
un rectangle. (Voir les modifications.)quad
: (1) initialiserid=1
; (2) le changementid/2
deid*2
lalower=
ligne; (3) effectuer une modification similaire àid*2+1
dans laupper=
ligne. (Je vais modifier ma réponse pour refléter cela.) Cela devrait également prendre en charge le calcul de la zone: selon votre SIG, toutes les zones seront positives ou toutes seront négatives. S'ils sont tous négatifs, inversez les listes pourx
ety
dedanscell.quadtree.leaf
.Voyez si cet algorithme donne suffisamment d'anonymat pour votre échantillon de données:
Par exemple, si le seuil minimum est 3:
la source
De manière similaire à la solution intéressante de Paulo, que diriez-vous d'utiliser un algorithme de subdivision en quatre arbres?
Définissez la profondeur à laquelle vous souhaitez que le quadtree se rende. Vous pouvez également avoir un nombre minimum ou maximum de points par cellule afin que certains nœuds soient plus profonds / plus petits que d'autres.
Subdivisez votre monde, jetez les nœuds vides. Rincer et répéter jusqu'à ce que les critères soient remplis.
la source
Une autre approche consiste à créer une grille très fine et à utiliser l'algorithme max-p. http://pysal.readthedocs.org/en/v1.7/library/region/maxp.html
la source