Come gestire etichette e bordi sconosciuti nel grafico Python

Oct 10 2020

Ho due array, a e b. Vorrei disegnare il networkxgrafico che raggruppa i valori vicini tra loro e etichettarli di conseguenza. Qualche idea su come farlo?

Risposte

1 mathfux Oct 11 2020 at 01:45

Trovare coppie vicine

Il tuo algoritmo trova il punto più vicino ba ogni punto di ama devi identificare un elenco di essi entro una certa soglia di distanza (che potrebbe essere vuota nella maggior parte dei casi). Ciò può essere ottenuto con l'assistenza di scipy.spatial.KDTree:

import numpy as np
from scipy.spatial import KDTree
from itertools import chain
def nearby_pts(a, b, distance):
    # indices of close points of `b` for each point of `a`
    a_data, b_data = np.expand_dims(a, axis=1), np.expand_dims(b, axis=1)
    idx = KDTree(b_data).query_ball_point(a_data, r=distance)
    return idx

Quindi puoi trovare archi che uniscono coppie di indici di punti vicini da aa b. Questo non può essere vettorializzato completamente ma ne ho ricavato il meglio che potevo:

def close_pairs(a, b, distance):
    pts = nearby_pts(a, b, distance).tolist()
    pts_flatten = list(chain(*pts))
    idx = np.repeat(np.arange(len(pts)), [len(n) for n in pts])
    return np.c_[idx, pts_flatten]

Produzione:

>>> close_pairs(a, b, distance=150)
[[0, 12], [1, 11], [2, 13], [3, 7], [5, 10], [5, 15], [6, 8], [7, 1], [8, 2], [9, 3], [9, 14], [10, 0], [11, 6], [12, 4], [13, 5], [13, 15], [14, 3], [15, 10]]

Tracciare un grafico

Ora sei pronto per creare un grafico dagli spigoli trovati ma prima devi rinominare una seconda sezione di nodes ( b) da non duplicare con asezione. Quindi puoi semplicemente aggiungere len(a)agli indici dei nodi di be il gioco è fatto:

import igraph as ig

pairs_relabel = close_pairs(a, b, distance=150) + [0, len(a)]
g = ig.Graph(n = len(a) + len(b))
g.add_edges(pairs_relabel)

pal = ig.drawing.colors.ClusterColoringPalette(2) #number of colors used is 2
color = pal.get_many([0]*len(a)+[1]*len(b)) #tags of colors
labels = np.r_[a.astype(int), b.astype(int)] #labels are integral values of nodes

ig.plot(g, bbox=(500, 300), vertex_size=24, 
        vertex_color = color, vertex_label_size=9, vertex_label = labels)