目标
使用python
的graph_tool
包,根据以下表格,生成网络关系图。
采样方法 | 大类 | 小类 |
---|---|---|
低空遥感解译 | 地面 | 裸土地,人工地面 |
地面影像解译 | 水生植物 | 水葫芦,荷叶,苦草,黑藻,水华,水白菜 |
RTK测量 | 禾本植物 | 狗牙根,华克拉莎,斑茅,苔草,芦苇,芦竹,杂茅 |
RTK测量 | 竹 | 风箱树,马甲子 |
RTK测量 | 灌木 | 车筒竹,泰竹,凤尾竹 |
RTK测量 | 乔木 | 旱柳,垂柳,桂花,乌桕,樟树,枫香,银杏,桉树,楝,榆树 |
低空遥感解译 | 水稻 | 已收割,已焚烧,禾苗 |
低空遥感解译 | 菜地 | 铺草,菜苗 |
地面影像解译 | 景观树 | 景观乔木,景观灌木 |
低空遥感解译 | 人造物 | 房屋,木桥,船,车辆 |
简介
Graph-tool 是一个高效的Python模块,用于图形 (又名网络)的操作和统计分析。 与大多数具有类似功能的其他 Python 模块相反,核心数据结构和算法是用C++实现的,广泛使用模板元编程,很大程度上基于Boost Graph Library。这赋予它与纯 C/C++ 库相当的 性能水平(在内存使用和计算时间方面)。
官网:https://graph-tool.skewed.de/
文档:https://graph-tool.skewed.de/static/doc/index.html
论坛:https://forum.skewed.de/c/graph-tool/5
GitLab:https://git.skewed.de/count0/graph-tool
该包的缺点也很明显:
- 不支持windows
- 文字不能换行(有人提到过,但作者摆了)https://git.skewed.de/count0/graph-tool/-/issues/549
- 不能根据指定长宽比绘图
数据
sample.csv
采样方法 大类 小类
低空遥感解译 地面 裸土地,人工地面
地面影像解译 水生植物 水葫芦,荷叶,苦草,黑藻,水华,水白菜
RTK测量 禾本植物 狗牙根,华克拉莎,斑茅,苔草,芦苇,芦竹,杂茅
RTK测量 竹 风箱树,马甲子
RTK测量 灌木 车筒竹,泰竹,凤尾竹
RTK测量 乔木 旱柳,垂柳,桂花,乌桕,樟树,枫香,银杏,桉树,楝,榆树
低空遥感解译 水稻 已收割,已焚烧,禾苗
低空遥感解译 菜地 铺草,菜苗
地面影像解译 景观树 景观树,景观灌木
低空遥感解译 人造物 房屋,木桥,船,车
代码
import numpy as np
from graph_tool.all import *
# 2字中间加空格
def space_in_name(name):
if len(name) == 2:
return f'{name[0]} {name[1]}'
return name
# 需要重点突出的类别
def bold_in_name(v):
if vname[v] in ['RTK测量', '桂花', '车筒竹', '华克拉莎', '水葫芦', '船']:
vfweight[v] = 1
vweight[v] = 0.5 * scale
vfsize[v] = 16 * scale
vsize[v] = 65 * scale
else:
vfweight[v] = 0
vweight[v] = 1 * scale
vfsize[v] = 12 * scale
vsize[v] = 50 * scale
scale = 5 # 总体缩放控制
# 画一个图B->A
g = Graph()
g.set_directed(True) # 设置为有向图
# 新建顶点属性
vname = g.new_vertex_property("string") # 顶点名称
vweight = g.new_vertex_property("float") # 顶点权重
vcolor = g.new_vertex_property("string") # 顶点边框颜色
vfcolor = g.new_vertex_property("string") # 顶点填充颜色
vsize = g.new_vertex_property("float") # 顶点大小
vfsize = g.new_vertex_property("float") # 顶点文字大小
vfweight = g.new_vertex_property("int") # 顶点文字粗细 0:正常 1:粗体
# 新建边属性
ecolor = g.new_edge_property("string") # 边颜色
emarker = g.new_edge_property("string") # 边标记(箭头)
# 加载数据
data_path = '/home/dl/temp/sample.csv'
data = np.loadtxt(data_path, dtype=np.str_, delimiter=' ', skiprows=1)
list_a = data[:, 0].tolist()
list_b = data[:, 1].tolist()
list_c = data[:, 2].tolist()
# 第一列去重,第三列分割+去重
set_a = list(set(list_a))
list_c = [i.split(',') for i in list_c]
set_c = list(set([j for i in list_c for j in i]))
# 添加顶点
v_a = []
for i in set_a:
# 添加顶点
v = g.add_vertex()
# 设置顶点属性
vname[v] = space_in_name(i)
vcolor[v] = "red"
vfcolor[v] = "lightpink"
bold_in_name(v)
vsize[v] = vsize[v] * 1.5
v_a.append(v)
v_b = []
for i in list_b:
v = g.add_vertex()
vname[v] = space_in_name(i)
vcolor[v] = "orange"
vfcolor[v] = "lightyellow"
bold_in_name(v)
vsize[v] = vsize[v] * 1.2
v_b.append(v)
v_c = []
for i in set_c:
v = g.add_vertex()
vname[v] = space_in_name(i)
vcolor[v] = "green"
vfcolor[v] = "lightgreen"
bold_in_name(v)
v_c.append(v)
# 添加边 a->b
for i in range(len(list_a)):
# 添加边
e = g.add_edge(v_a[set_a.index(list_a[i])], v_b[i])
# 设置边属性
ecolor[e] = "darkred"
emarker[e] = "arrow"
# 添加边 b-c
for i in range(len(list_b)):
for j in range(len(list_c[i])):
e = g.add_edge(v_b[i], v_c[set_c.index(list_c[i][j])])
ecolor[e] = "darkorange"
emarker[e] = "none"
# 画图 https://graph-tool.skewed.de/static/doc/autosummary/graph_tool.draw.graph_draw.html
graph_draw(g, output="/home/dl/temp/fig.png",
output_size=(int(1000*scale), int(1000*scale)), # 画布大小
pos=sfdp_layout(g, vweight=vweight, p=4), # 布局算法 https://graph-tool.skewed.de/static/doc/autosummary/graph_tool.draw.sfdp_layout.html
vertex_text=vname,
vertex_color=vcolor,
vertex_fill_color=vfcolor,
vertex_font_weight=vfweight,
vertex_font_size=vfsize,
vertex_pen_width=1*scale,
vertex_text_position=-2, # 默认-1:顶点大小随文字缩放, -2:顶点大小不随文字缩放,由vertex_size控制
vertex_size=vsize,
edge_color=ecolor,
edge_pen_width=1.2*scale,
edge_marker_size=10*scale,
edge_end_marker=emarker,
)