Reti asimmetriche
E se la relazione tra nodi fosse "figlio di"? Allora la relazione non è più simmetrica. Se A è figlio di B, B non è figlio di A. Una rete in cui la relazione è asimmetrica (A è collegato a B, ma non significa necessariamente che B sia collegato ad A) è detta rete asimmetrica. Possiamo costruire una rete asimmetrica in NetworkX usando il metodo DiGraph, abbreviazione di Directional Graph. Creiamo un grafo asimmetrico.
G_asymmetric = nx.DiGraph()
G_asymmetric.add_edge('A','B')
G_asymmetric.add_edge('A','D')
G_asymmetric.add_edge('C','A')
G_asymmetric.add_edge('D','E')
Ora visualizziamolo. Possiamo usare la funzione draw_networkx() come prima. Tuttavia, è possibile che i nodi non si distanzino e non siano ben visibili nella rete disegnata. Per ovviare a questo, possiamo usare una funzione che forzi un layout, posizionando i nodi in modo che siano chiaramente distinguibili. Possiamo farlo usando la funzione spring_layout(), seguita da draw_networkx().
nx.spring_layout(G_asymmetric)
nx.draw_networkx(G_asymmetric)
Sotto puoi vedere la rete con e senza il comando di layout. Quella ottenuta usando il layout è più chiara.

Reti pesate
Finora abbiamo avuto reti senza pesi, ma è possibile costruire reti con pesi: ad esempio, se nella nostra rete iniziale consideriamo come peso il numero di film fatti insieme, otterremo una rete pesata. Creiamone una di nuovo con gli attori, ma questa volta aggiungiamo un peso alla rete: ogni arco ha un peso che indica il numero di film fatti insieme.
G_weighted = nx.Graph()
G_weighted.add_edge('Amitabh Bachchan','Abhishek Bachchan', weight=25)
G_weighted.add_edge('Amitabh Bachchan','Aaamir Khan', weight=8)
G_weighted.add_edge('Amitabh Bachchan','Akshay Kumar', weight=11)
G_weighted.add_edge('Amitabh Bachchan','Dev Anand', weight=1)
G_weighted.add_edge('Abhishek Bachchan','Aaamir Khan', weight=4)
G_weighted.add_edge('Abhishek Bachchan','Akshay Kumar',weight=7)
G_weighted.add_edge('Abhishek Bachchan','Dev Anand', weight=1)
G_weighted.add_edge('Dev Anand','Aaamir Khan',weight=1)

La figura sopra mostra la rete pesata degli attori in un layout circolare. Lo spessore dell’arco indica il peso tra due nodi.
Multigrafo
Possiamo assegnare diversi attributi agli archi. Ad esempio, possiamo definire una relazione di vicinato tra due nodi "A" e "B" usando l’attributo relation. Se in una rete due nodi sono collegati da due archi diversi (relazioni), abbiamo un multigrafo. Possiamo creare un multigrafo utilizzando la classe MultiGraph.
G = nx.MultiGraph()
G.add_edge('A','B',relation ='neighbor')
G.add_edge('A','B',relation='friend)
G.add_edge('B','C', relation='neighbor')
G.add_edge('D','C',relation='friend')
Questo codice costruirà un grafo con due archi tra A e B. Possiamo verificare le connessioni usando G.edges(); l’output mostrerà:
MultiEdgeDataView([('A', 'B', {'relation': 'neighbor'}), ('A', 'B', {'relation': 'friend'}), ('B', 'C', {'relation': 'neighbor'}), ('B', 'D', {'relation': 'neighbor'}), ('C', 'D', {'relation': 'friend'})])
Connettività della rete
Ora che la rete è creata, possiamo sapere di più su un particolare nodo? Certo, esploriamone alcuni aspetti.
Grado
Il grado di un nodo definisce il numero di connessioni che un nodo ha. NetworkX ha la funzione degree che possiamo usare per determinare il grado di un nodo nella rete.
nx.degree(G_symmetric, 'Dev Anand`)
Questo restituirà il valore 3, poiché Dev Anand ha lavorato con soli tre attori nella rete.
Coefficiente di clustering
Si osserva che le persone che condividono connessioni in una rete sociale tendono a formare associazioni. In altre parole, in una rete sociale c’è una tendenza a formare cluster. Possiamo determinare i cluster di un nodo, ovvero il coefficiente di clustering locale, che è la frazione delle coppie di amici del nodo (cioè connessioni) che sono connessi tra loro. Per determinare il coefficiente di clustering locale, utilizziamo la funzione nx.clustering(Graph, Node).
Nella rete simmetrica degli attori, troverai che Dev Anand ha un coefficiente di clustering locale pari a 1 e Abhishek Bachchan ha un coefficiente di clustering locale pari a 0,67.
Il coefficiente di clustering medio (somma di tutti i coefficienti di clustering locali divisa per il numero di nodi) per la rete simmetrica degli attori è 0,867. Possiamo ottenerlo usando:
nx.average_clustering(G_symmetric)
Distanza
Possiamo anche determinare in NetworkX il cammino più breve tra due nodi e la sua lunghezza usando rispettivamente le funzioni nx.shortest_path(Graph, Node1, Node2) e nx.shortest_path_length(Graph, Node1, Node2).
Eseguendo
nx.shortest_path(G_symmetric, 'Dev Anand', 'Akshay Kumar')
Restituisce
['Dev Anand', 'Amitabh Bachchan', 'Akshay Kumar']
Possiamo trovare la distanza di un nodo da ogni altro nodo nella rete usando l’algoritmo di visita in ampiezza (breadth-first search), a partire da quel nodo. networkX fornisce la funzione bfs_tree per farlo. Quindi, se provi T = nx.bfs_tree(G_symmetric, 'Dev Anand') e disegni questo albero, otterremo una struttura che indica come possiamo raggiungere gli altri nodi della rete partendo da Dev Anand

Eccentricità
L’eccentricità di un nodo A è definita come la distanza massima tra A e tutti gli altri nodi. Può essere trovata usando la funzione nx.eccentricity(). Nella rete simmetrica degli attori, Dev Anand ha un’eccentricità pari a 2 e Abhishek Bachchan ha un’eccentricità pari a 1 (è connesso a tutti).
Influencer nella rete
Finora abbiamo visto alcune misure di distanza nella rete; sono utili per capire come l’informazione si diffonderà attraverso la rete. In questa sezione impareremo come trovare i nodi (individui) più importanti nella rete. Questi parametri sono chiamati misure di centralità.
Ti ricordi la ragazza popolare del liceo o il miglior giocatore di baseball della scuola? Erano le persone che potevano rendere la tua esperienza al liceo un inferno o un paradiso. Cosa dava loro questo potere? Le misure di centralità possono aiutarci a identificare popolarità, più apprezzati e maggiori influencer all’interno della rete.
Centralità di grado
Le persone più popolari o più apprezzate di solito sono quelle che hanno più amici. La centralità di grado è una misura del numero di connessioni che un determinato nodo ha nella rete. Si basa sul fatto che i nodi importanti hanno molte connessioni. NetworkX ha la funzione degree_centrality() per calcolare la centralità di grado di tutti i nodi di una rete.
Centralità vettore proprio
Non conta solo con quante persone si è collegati, ma anche con che tipo di persone si è collegati: questo può determinare l’importanza di un nodo. Sulle strade di Delhi, quando la polizia stradale ferma qualcuno per una violazione, la prima frase che sente spesso è "Sai con chi sono imparentato?".
La centralità vettore proprio misura esattamente questo. Stabilisce che un nodo è importante se è connesso ad altri nodi importanti. Possiamo usare la funzione eigenvector_centrality() di NetworkX per calcolare la centralità vettore proprio di tutti i nodi in una rete.
L’algoritmo Pagerank di Google è una variante dell’algoritmo di centralità vettore proprio.
Centralità di intermediazione
La centralità di intermediazione è la centralità del controllo. Rappresenta la frequenza con cui un punto ricorre sulle geodetiche (cammini minimi) che collegano coppie di punti. Quantifica quante volte un particolare nodo ricorre nel cammino più breve scelto tra due altri nodi. I nodi con alta centralità di intermediazione svolgono un ruolo significativo nel flusso di comunicazione/informazioni all’interno della rete. I nodi con alta centralità di intermediazione possono esercitare un controllo strategico e influenza sugli altri. Un individuo in una posizione così strategica può influenzare l’intero gruppo, trattenendo o alterando l’informazione durante la trasmissione.
Networkx ha la funzione betweenness_centrality() per misurarla nella rete. Ha opzioni per scegliere se vogliamo valori normalizzati, includere o meno i pesi nel calcolo della centralità e includere o meno gli estremi nel conteggio dei cammini minimi.
Mettere tutto insieme
Partiamo dai dati di Facebook: per la nostra analisi useremo il dataset combinato delle ego networks di Facebook, che contiene la rete aggregata delle liste di amici di dieci individui. Puoi scaricare il file necessario facebook_combined.txt dal sito della Stanford University.
Puoi ottenere i tuoi dati Facebook/Twitter usando le API di Facebook/Twitter. Restiamo in attesa del prossimo tutorial in cui impareremo a usare le API di Facebook e Twitter per ottenere i dati e applicare quanto visto qui per analizzarli.
Leggiamo il file e costruiamo il grafo:
G_fb = nx.read_edgelist("facebook_combined.txt", create_using = nx.Graph(), nodetype=int)
La rete è composta da 4.039 nodi, collegati da 88.234 archi! Sì, è una rete grande. Puoi ottenere queste informazioni con la funzione info().
[In]: print(nx.info(G_fb))
[Out]: Name:
Type: Graph
Number of nodes: 4039
Number of edges: 88234
Average degree: 43.6910
Qui sotto puoi vedere la rete:

Possiamo anche visualizzare la rete in modo che il colore del nodo vari con il grado e la dimensione del nodo con la centralità di intermediazione. Il codice per farlo è:
pos = nx.spring_layout(G_fb)
betCent = nx.betweenness_centrality(G_fb, normalized=True, endpoints=True)
node_color = [20000.0 * G_fb.degree(v) for v in G_fb]
node_size = [v * 10000 for v in betCent.values()]
plt.figure(figsize=(20,20))
nx.draw_networkx(G_fb, pos=pos, with_labels=False,
node_color=node_color,
node_size=node_size )
plt.axis('off')
E il grafo risultante è:

Puoi anche conoscere le etichette dei nodi con la centralità di intermediazione più alta usando:
sorted(betCent, key=betCent.get, reverse=True)[:5]
La tabella seguente elenca le cinque etichette di nodo con i valori di centralità più alti.
| Centralità di grado | Centralità vettore proprio | Centralità di intermediazione |
|---|---|---|
| 107 | 1912 | 107 |
| 1684 | 2266 | 1684 |
| 1912 | 2206 | 3437 |
| 3437 | 2233 | 1912 |
| 0 | 2464 | 1085 |
Vediamo che alcuni nodi sono comuni tra la centralità di grado, che è una misura del grado, e la centralità di intermediazione, che controlla il flusso di informazioni. È naturale che i nodi più connessi ricadano anche sui cammini minimi tra altri nodi. Il nodo 1912 è un nodo importante poiché risulta cruciale secondo tutte e tre le misure di centralità considerate.
Riferimenti
- I dati sugli attori sono stati ottenuti dal sito IMDB
- Il posto migliore per saperne di più su NetworkX e le sue funzioni è la sua documentazione
Se vuoi approfondire la Social Network Analysis in Python, segui il corso di DataCamp Analyzing Social Media Data in Python.


Se vuoi imparare l’Analisi delle Reti, segui il corso di DataCamp Network Analysis in Python (Part 1).
Le reti sono ovunque: reti stradali, una rete di amici e follower sui social media, e la rete dei colleghi d’ufficio. Svolgono un ruolo significativo nella nostra vita quotidiana, dalla diffusione di informazioni utili fino all’influenza sulle elezioni nazionali. La capacità di analizzare queste reti e prendere decisioni informate sulla base dei risultati è una competenza importante per qualsiasi data analyst.
Questo tutorial si concentra sull’insegnamento della social network analysis (SNA) usando Python e NetworkX, una libreria Python per lo studio della struttura, della dinamica e delle funzioni delle reti complesse. Questo tutorial presume che il lettore conosca la sintassi di base di Python; non è richiesta alcuna conoscenza preliminare di SNA.
Introduzione
Iniziamo chiarendo cosa intendiamo per Reti sociali. Qui sotto vedi una rete di attori di Bollywood come nodi. Sono collegati con linee continue se hanno lavorato insieme in almeno un film.
Possiamo quindi vedere che sia Amitabh Bachchan sia Abhishek Bachchan hanno recitato con tutti gli attori della rete, mentre Akshay Kumar ha lavorato solo con i due Bachchan. Interessante, vero?
Anche questa è una rete sociale. Qualsiasi rete con connessioni tra individui, dove le connessioni rappresentano la relazione tra loro, è una rete sociale. Analizzare queste reti può darci grandi intuizioni sulle persone nella rete, come chi sono i veri influencer, chi è il più connesso, ecc.
Ogni rete è composta da:
Creare una rete con NetworkX
Esistono molti tipi di reti. Useremo NetworkX per sviluppare e analizzare queste diverse reti. Per iniziare, devi installare networkX: puoi usare:
oppure, se lavori in Anaconda
Questo installerà l’ultima versione di networkx. I codici in questo tutorial sono stati eseguiti con Python=3.5, NetworkX = versione 2.0.
Reti simmetriche
La prima rete di attori che abbiamo creato sopra è una rete simmetrica perché la relazione "lavorare insieme in un film" è una relazione simmetrica. Se A è in relazione con B, anche B è in relazione con A. Creiamo la rete vista sopra in NetworkX.
Useremo il metodo
Graph()per creare una nuova rete eadd_edge()per aggiungere un arco tra due nodi.Ora visualizziamo la rete che abbiamo appena costruito usando
nx.draw_networkx(G_symmetric).