2015-07-02 32 views
1

我正在學習igraph,通過關注this tutorialigraph通用屬性選擇功能

這裏是一個語法從教程,我不熟悉前:

# g is a Graph object 
# g.vs are vertices of g 
>>> g.vs.select(age_lt=30) 
# this returns vertices which has "age" attribute less than 30 

我需要更多的東西通用

更具體地說,我想得到其屬性atr小於c的頂點。說,atrstringcint

我想:

>>> atr = 'age' 
>>> c = 30 
>>> g.vs.select(atr + '_lt'= c) 

不過,我得到一個SyntaxError

SyntaxError: keyword can't be an expression

我不想做手工,如:

>>> [v for v in g.vs if v[atr] < c] 

,因爲我的圖是

回答

2

你可以使用字典和str.format:

atr = 'age' 
c = 30 

g.vs(**{'{}_lt'.format(atr): c} 

如果您擔心內存的你也可以使用一個創記錄:

(v for v in g.vs if v[atr] < c) 

都返回相同的輸出:

In [2]: g = Graph([(0,1), (0,2), (2,3), (3,4), (4,2), (2,5), (5,0), (6,3), (5,6)]) 

In [3]: g.vs["name"] = ["Alice", "Bob", "Claire", "Dennis", "Esther", "Frank", "George"] 
In [4]: g.vs["age"] = [25, 31, 18, 47, 22, 23, 50] 
In [5]: g.vs["gender"] = ["f", "m", "f", "m", "f", "m", "m"] 
In [6]: g.es["is_formal"] = [False, False, True, True, True, False, True, False, False] 
In [7]: atr = 'age'  
In [8]: c = 30  
In [9]: list(g.vs(**{'{}_lt'.format(atr): c})) 
Out[9]: 
[igraph.Vertex(<igraph.Graph object at 0x7f06ae24f810>,0,{'gender': 'f', 'age': 25, 'name': 'Alice'}), 
igraph.Vertex(<igraph.Graph object at 0x7f06ae24f810>,2,{'gender': 'f', 'age': 18, 'name': 'Claire'}), 
igraph.Vertex(<igraph.Graph object at 0x7f06ae24f810>,4,{'gender': 'f', 'age': 22, 'name': 'Esther'}), 
igraph.Vertex(<igraph.Graph object at 0x7f06ae24f810>,5,{'gender': 'm', 'age': 23, 'name': 'Frank'})] 

In [10]: list(v for v in g.vs if v[atr] < c) 
Out[10]: 
[igraph.Vertex(<igraph.Graph object at 0x7f06ae24f810>,0,{'gender': 'f', 'age': 25, 'name': 'Alice'}), 
igraph.Vertex(<igraph.Graph object at 0x7f06ae24f810>,2,{'gender': 'f', 'age': 18, 'name': 'Claire'}), 
igraph.Vertex(<igraph.Graph object at 0x7f06ae24f810>,4,{'gender': 'f', 'age': 22, 'name': 'Esther'}), 
igraph.Vertex(<igraph.Graph object at 0x7f06ae24f810>,5,{'gender': 'm', 'age': 23, 'name': 'Frank'})] 

你不會在所有的len等等,但它似乎非常有效,如果你只是想過濾元素:

In [14]: timeit list(v for v in g.vs if v[atr] < c) 
100000 loops, best of 3: 4.7 µs per loop 

In [15]: timeit list(g.vs(**{'{}_lt'.format(atr): c})) 
100000 loops, best of 3: 14.5 µs per loop 
+2

這兩個答案都很有幫助,但我會將此標記爲提及速度方面和作爲第一個答案的答案。 – Sait

2

When the first parameter to select is a callable,頂點是如果可調用返回True選擇。

通過這種方式,您可以應用相對較複雜的查詢。例如:

import igraph 

G = igraph.Graph() 
G.add_vertex("John", age=22) 
G.add_vertex("Vilma", age=20) 
G.add_edge("John", "Vilma") 
vRes = G.vs.select(lambda x:x["name"]=="John" and x["age"]>20) 
#Or, with query parameters as below 
#someAttribute = "age" 
#someValue = 20 
#vRes = G.vs.select(lambda x:x[someAttribute] > someValue) 

在上述lambda,自變量x是一個igraph::Vertex它提供了訪問的所有頂點的屬性。

A similar interface存在選擇邊緣。

希望這會有所幫助。

+0

謝謝。我也不知道這個語法。我很好奇是否'(v for g.vs if v [atr] 20)'有任何性能差異... – Sait

+1

在這之後我也很好奇。所有'select'確實是'filtered_idxs = [i for i,v in enumerate(values)if func(v,value)]'這是一個列表解析,但上面提到的生成器表達式會返回一個更高效的迭代器,特別是如果過濾的節點只被遍歷一次。 (http://legacy.python.org/dev/peps/pep-0289/)。 –

+1

我實際上只是檢查[同樣的事情](http://igraph.org/python/doc/igraph-pysrc.html#VertexSeq.select)。 :-) – Sait