总结
在一张庞大的网络中, 有很多的节点,
节点与节点之间,可能有边,也可能没有边。
节点,有属性。属性和属性值之间的关系,就像dict字典一样。
边,也有属性
度中心性
中介中心性
1/什么是networkx
有一个关于图论和网络建模的工具叫 NetworkX,
它是用 Python 语言开发的扩展包,内置了常用的图与网络分析算法,可以方便我们进行网络数据分析
2/社交网络图的增删改查
初始化(构建)一张社交网络图
# 图的形式有很多种,比如有向图,无向图,多重有向图,多重无向图
多重指的是节点之间存在多条边, 每条边的含义不同.
比如有的边代表关注, 有的边代表发过信息, 有的边代表转过账等.
当然我们也可以把多条边,通过某种方式最后构建成一条边, 这个需要看具体的业务场景.
import networkx as nx
# 初始化社交网络图,图中没有节点和边关系
G = nx.Graph() # 无向图,节点之间的边没有方向,且2个节点之间只有一条边
G = nx.DiGraph() # 有向图,节点之间的边有方向,且2个节点之间只有一条边
G = nx.MultiGraph() # 多重无向图,边没有方向,两节点之间可以有多条边,不同的边代表不同的意思
G = nx.MultiDigraph() # 多重有向图,边有方向,两节点之间可以有多条边,不同的边代表不同的意思
添加节点
# 一次添加1个节点
G.add_node("node_name") # add_node(),而不是add_nodes(),说明这是一次添加一个节点
# 批量添加节点
G.add_nodes_from( ['b','c','d','e'] ) # add_nodes_from(),而不是add_node_from()
# 加环,add_cycle()函数意味着同时添加了节点和边关系
G.add_cycle(['f','g','h','j'])
# 添加节点的同时,还可以添加节点的属性,
# 一个节点可以有一个或者任意多个属性
# 节点的属性名称和属性值之间的关系,类似字典dict。属性名称不能重复。
G.add_node(1,weight=2) # 增加节点1,节点1权重属性值为2
G.nodes[1]["age"] = 30 # 给节点1增加age属性
G.add_node(2,weight=3) # 增加节点2,同时给节点2添加权重属性为3
G.nodes[0]["foo"] = "bar" # 添加节点0的同时,也添加了foo属性
list(G.nodes(data=True)) # 查看节点值及其属性,data=True是返回属性
# 输出结果:
[(0, {'foo': 'bar'}), (1, {'weight':2, 'time': '5pm'}), (2, {'weight':3})]
添加边
# 每次添加一条边
G.add_edge(2,3) # 添加一条边2-3(这里其实是一举两得,把节点和边都添加进去了)
G.add_edge(3,2) # 如果G是无向图,边3-2与边2-3则是同一条边,只会保留一条边(保留后添加的)
# 一次性添加多条边
# 一次性添加多条边,用add_edges_from()函数,添加边,同时就会把节点添加进去
G.add_edges_from( [(1,2),(1,3),(2,4),(2,5),(3,6),(4,8),(5,8),(3,7)] )
# 因为是无向图,所以如果边已经存在,则后添加的边会覆盖之前添加的边
# add_edge()和add_edges_from()函数只是添加了边,并没有添加边的属性。
添加边的属性,一条边可以有任意多个属性
给这三条边设置属性score,边的属性单独放在一个字典中dict
G.add_edges_from( [(‘小红’, ‘小黄’, {‘score’:70}),
(‘小红’, ‘小青’, {‘score’:80}),
(‘小黄’, ‘小青’, {‘score’:90})
] )
单独给一条边添加属性:
G[node][node]['属性名'] = '属性值'
查看边的所有属性
for (u,v,w) in g.edges(data=True): # data=True是返回属性,若是False则只返回节点
u 是节点
v 是节点
w 是连接uv两个节点的边上的所有属性,是一个字典结构。
添加带有权重的边
批量添加带权重的边(以下三种形式都可以实现):
G.add_weighted_edges_from([ (‘小红’, ‘小黄’, 7.0),
(‘小红’, ‘小青’, 10),
(‘小黄’, ‘小青’, 3)] )
#元组中的第三个参数默认为weight属性值
G.add_edges_from([(‘小红’, ‘小黄’, {‘weight’:7.0}),
(‘小红’, ‘小青’, {‘weight’:10}),
(‘小黄’, ‘小青’, {‘weight’:3})] )
获取节点和边,以及节点和边的数量
G.nodes()
G.edges()
G.number_of_nodes()
G.number_of_edges()
清空网络图
把网络图中的节点和边关系全部删除,网络图还是存在的,是一张空的网络图
G.clear()
修改节点的属性,修改边的属性
修改节点的属性:
G.nodes[0]["foo"] = "bar"
修改边的属性:
G.edges[‘小红’,‘小黄’][‘weight’] =10
获得边的属性
如果想读取权重,可以使用get_edge_data方法,它接受两个参数u和v,即边的起止点。
例如:
G.get_edge_data(0,1)
输出{'weight': 3.0},这是一个字典结构
删除节点,删除边
删除节点
G.remove_node(node)
G.remove_nodes_from(['b','c','d','e'])
删除边(注意:真是把边删除了,节点还是存在的)
G.remove_edge(node1,node2) # 一次删除一条边
G.remove_edges_from([]) # 批量删除多条边
保存社交网络图
nx.write_gml(G,"path_where_graph_should_be_saved.gml")
# 以.gml作为后缀,
读取图
G = nx.read_gml("path_to_graph_graph.gml")
有向图和无向图之间是可以相互转化的
G1 = G.to_undirected() # 有向图-->无向图
G1 = G.to_directed() # 无向图-->有向图
在社交网络图中,给图添加属性
上图中的例子:
首先创建一个了含有3个节点的社交网络图
然后计算图中各个节点的中介中心性,得到的是一个字典格式
然后通过set_node_attrbutes()函数给社交网络图添加属性
set_node_attrbutes(g,attr_name,attr_value)"
该函数有3个参数:
社交网络g,属性名称,属性值
G.subgraph(nodes) 获得子图
# 从一张总的社交网络图中,指定节点,获得一张子图。
g = nx.path_graph(50) # 创建一张含有50个节点的图
nodes = ['A', 'C', 'B']
subgraph = g.subgraph(nodes)
图于图之间的合并
有2种方式
<1>G3=nx.disjoint_union(G1,G2)
下图中,虽然把2张社交网络图放在了一站图中,但是公共节点(0,1,2)并没有合并在一起,
所以这个函数不好
<2>g3 = nx.compose(g1,g2)
下图中,公共节点已经合并了
nx.path_graph()
G=nx.path_graph(8)
该函数的作用是创建一个含有8个节点的社交网络图,形状类似于单链表的形式
下图只看左边即可
nx.has_path(G,source,target)
# 判断2节点是否连通
import networkx as nx
nx.has_path(G,source,target)
nx.complete_graph()
g=nx.complete_graph(3)
该函数是创建两两相连的社交网络图
下图只看中间即可
通过nx.bfs_successors(g,source=node,depth_limit=depth)
bfs_successors()函数是得到指定节点的所有层次的相邻节点
通过一定的函数改造,可以得到指定节点的指定层次的相邻节点。
获取结点i的邻居节点
G.neighbors(i)