Mejores prácticas para consultar gráficos por atributos de borde y nodo en NetworkX

Uso de NetworkX, y nuevo en la biblioteca, para una consulta de análisis de redes sociales. Por consulta, me refiero a seleccionar / crear subgrafos por atributos de los nodos de ambos bordes donde los bordes crean una ruta y los nodos contienen atributos. El gráfico está utilizando un MultiDiGraph de la forma

G2 = nx.MultiDiGraph() G2.add_node( "UserA", { "type" :"Cat" } ) G2.add_node( "UserB", { "type" :"Dog" } ) G2.add_node( "UserC", { "type" :"Mouse" } ) G2.add_node( "Likes", { "type" :"Feeling" } ) G2.add_node( "Hates", { "type" :"Feeling" } ) G2.add_edge( "UserA", 'Hates' , statementid="1" ) G2.add_edge( "Hates", 'UserB' , statementid="1" ) G2.add_edge( "UserC", 'Hates' , statementid="2" ) G2.add_edge( "Hates", 'UserA' , statementid="2" ) G2.add_edge( "UserB", 'Hates' , statementid="3" ) G2.add_edge( "Hates", 'UserA' , statementid="3" ) G2.add_edge( "UserC", 'Likes' , statementid="3" ) G2.add_edge( "Likes", 'UserB' , statementid="3" ) 

Consultado con

 for node,data in G2.nodes_iter(data=True): if ( data['type'] == "Cat" ): # get all edges out from these nodes #then recursively follow using a filter for a specific statement_id #or get all edges with a specific statement id # look for with a node attribute of "cat" 

¿Hay una mejor manera de consultar? ¿O es la mejor práctica crear iteraciones personalizadas para crear subgrafos?

Alternativamente (y una pregunta separada), el Gráfico podría simplificarse, pero no estoy usando el gráfico siguiente porque los objetos del tipo “odia” tendrán predecesores. ¿Esto haría la consulta más simple? Parece más fácil iterar sobre los nodos

 G3 = nx.MultiDiGraph() G3.add_node( "UserA", { "type" :"Cat" } ) G3.add_node( "UserB", { "type" :"Dog" } ) G3.add_edge( "UserA", 'UserB' , statementid="1" , label="hates") G3.add_edge( "UserA", 'UserB' , statementid="2" , label="hates") 

Otras notas:

  • ¿Quizás add_path agrega un identificador a la ruta creada?
  • iGraph tiene una buena función de consulta g.vs.select()

Sobre la base de la respuesta de @Aric , puedes encontrar peces rojos como este:

 red_fish = set(n for u,v,d in G.edges_iter(data=True) if d['color']=='red' for n in (u, v) if G.node[n]['label']=='fish') print(red_fish) # set([2]) 

Es bastante sencillo escribir una sola línea para hacer una lista o un generador de nodos con una propiedad específica (los generadores se muestran aquí)

 import networkx as nx G = nx.Graph() G.add_node(1, label='one') G.add_node(2, label='fish') G.add_node(3, label='two') G.add_node(4, label='fish') # method 1 fish = (n for n in G if G.node[n]['label']=='fish') # method 2 fish2 = (n for n,d in G.nodes(data=True) if d['label']=='fish') print(list(fish)) print(list(fish2)) G.add_edge(1,2,color='red') G.add_edge(2,3,color='blue') red = ((u,v) for u,v,d in G.edges(data=True) if d['color']=='red') print(list(red)) 

Si su gráfico es grande y fijo y desea realizar búsquedas rápidas, podría hacer un “diccionario inverso” de los atributos como este,

 labels = {} for n, d in G.nodes(data=True): l = d['label'] labels[l] = labels.get(l, []) labels[l].append(n) print labels 

Para seleccionar bordes basados ​​en atributos de bordes Y nodos, es posible que desee hacer algo como esto, utilizando su gráfica, G2:

 def select(G2, query): '''Call the query for each edge, return list of matches''' result = [] for u,v,d in G2.edges(data=True): if query(u,v,d): result.append([(u,v)]) return result # Example query functions # Each assumes that it receives two nodes (u,v) and # the data (d) for an edge def dog_feeling(u, v, d): return (d['statementid'] == "3" and G2.node[u]['type'] == "Dog" or G2.node[u]['type'] == "Dog") def any_feeling(u,v,d): return (d['statementid'] == "3" and G2.node[u]['type'] == "Feeling" or G2.node[u]['type'] == "Feeling") def cat_feeling(u,v,d): return (G2.node[u]['type'] == "Cat" or G2.node[v]['type'] == "Cat") # Using the queries print select(G2, query = dog_feeling) print select(G2, query = any_feeling) print select(G2, query = cat_feeling) 

Esto abstrae el proceso de iteración en la función select() y puede escribir sus consultas como funciones individuales y comprobables.