使用带量词的命题形式的节点调整网图中的字体大小?
Adjust fontsize in netgraph with nodes in form of proposition with quantifiers?
我正在使用 netgraph 可视化我的 networkx 图。我现在的问题是,公式的可视化以自然的方式不如我预期的那么漂亮。这是我的示例图:
import networkx as nx
from netgraph import Graph # pip install netgraph
import matplotlib.pyplot as plt
node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}
graph = nx.from_edgelist(edge_labels, nx.DiGraph())
Graph(graph, node_labels=node_labels, edge_labels=edge_labels,
node_color=color_map, node_edge_color=color_map, arrows=True)
plt.show()
输出(直接/放大后):
:
我现在的问题:
- 他们是调整节点字体大小的方法吗?
- 是否可以旋转边缘标签使其水平对齐?
Plotly 有一个 very nice example of network graph 可以很容易地重新适应您的需要。
这是您的问题的答案。
# Packages import
import networkx as nx
import plotly.graph_objs as go
# Your input data
node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}
# Create DiGraph
G=nx.DiGraph()
# Add nodes and edges
G.add_nodes_from(list(node_labels.keys()), weight=15)
G.add_edges_from(list(edge_labels.keys()))
# Create Positions
pos = nx.planar_layout(G) # nx.random_layout(G), ...
# Create edges for plot and edge annotations
edge_x = []
edge_y = []
edge_label_x = []
edge_label_y = []
for edge in G.edges:
x0, y0 = pos[edge[0]][0], pos[edge[0]][1]
x1, y1 = pos[edge[1]][0], pos[edge[1]][1]
edge_x.append(x0)
edge_x.append(x1)
edge_x.append(None)
edge_y.append(y0)
edge_y.append(y1)
edge_y.append(None)
edge_label_x.append((x0+x1)/2)
edge_label_y.append((y0+y1)/2)
# Make go.Scatter for edges
edge_trace = go.Scatter(
x=edge_x, y=edge_y,
line=dict(width=0.5, color='#888'),
hoverinfo='none',
mode='lines'
)
# Create nodes for plot
node_x = []
node_y = []
node_color = []
for node in G.nodes:
x, y = pos[node][0], pos[node][1]
node_x.append(x)
node_y.append(y)
node_color.append(color_map[node])
# Make go.Scatter for nodes
node_trace = go.Scatter(
x=node_x, y=node_y,
mode='markers+text',
hoverinfo='text',
text=list(node_labels.values()),
textposition="middle center", # ['top left', 'top center', 'top right', 'middle left',
# 'middle center', 'middle right', 'bottom left',
# 'bottom center', 'bottom right']
textfont=dict(
family="sans serif",
size=10, # <-- Here you change the node text size
color="black"
),
marker=dict(
showscale=False,
color=node_color,
size=46,
line_width=1
)
)
# Make edge annotations
edge_annotations = []
for label, x, y in zip(list(edge_labels.values()), edge_label_x, edge_label_y):
edge_annotations.append(
dict(
x=x, y=y,
showarrow=False,
hovertext='none',
ax=0,
ay=0,
bgcolor="white",
opacity=0.85,
text=label,
font=dict(
family="sans serif",
size=14,
color="black",
)
)
)
# Make go.Figure
fig = go.Figure(
data=[edge_trace, node_trace],
layout=go.Layout(
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
title='<br>Network graph',
titlefont_size=16,
showlegend=False,
hovermode='closest',
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
autosize=False,
width=700,
height=700,
margin=dict(l=50, r=50, b=100, t=100, pad=4),
)
)
# Add edge annotations to go.Figure
for edge_annotation in edge_annotations:
fig.add_annotation(edge_annotation)
# Show go.Figure
fig.show()
导致:
编辑:
使用 Plotly 添加边缘方向有点棘手(). Fortunately there is a github project 我们可以从中借用一个函数,通过考虑节点大小向边缘添加箭头。
现在的代码是:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri May 15 11:45:07 2020
@author: aransil
"""
import math
# Start and end are lists defining start and end points
# Edge x and y are lists used to construct the graph
# arrowAngle and arrowLength define properties of the arrowhead
# arrowPos is None, 'middle' or 'end' based on where on the edge you want the arrow to appear
# arrowLength is the length of the arrowhead
# arrowAngle is the angle in degrees that the arrowhead makes with the edge
# dotSize is the plotly scatter dot size you are using (used to even out line spacing when you have a mix of edge lengths)
def addEdge(start, end, edge_x, edge_y, lengthFrac=1, arrowPos = None, arrowLength=0.025, arrowAngle = 30, dotSize=20):
# Get start and end cartesian coordinates
x0, y0 = start
x1, y1 = end
# Incorporate the fraction of this segment covered by a dot into total reduction
length = math.sqrt( (x1-x0)**2 + (y1-y0)**2 )
dotSizeConversion = .0565/20 # length units per dot size
convertedDotDiameter = dotSize * dotSizeConversion
lengthFracReduction = convertedDotDiameter / length
lengthFrac = lengthFrac - lengthFracReduction
# If the line segment should not cover the entire distance, get actual start and end coords
skipX = (x1-x0)*(1-lengthFrac)
skipY = (y1-y0)*(1-lengthFrac)
x0 = x0 + skipX/2
x1 = x1 - skipX/2
y0 = y0 + skipY/2
y1 = y1 - skipY/2
# Append line corresponding to the edge
edge_x.append(x0)
edge_x.append(x1)
edge_x.append(None) # Prevents a line being drawn from end of this edge to start of next edge
edge_y.append(y0)
edge_y.append(y1)
edge_y.append(None)
# Draw arrow
if not arrowPos == None:
# Find the point of the arrow; assume is at end unless told middle
pointx = x1
pointy = y1
eta = math.degrees(math.atan((x1-x0)/(y1-y0))) if y1!=y0 else 90.0
if arrowPos == 'middle' or arrowPos == 'mid':
pointx = x0 + (x1-x0)/2
pointy = y0 + (y1-y0)/2
# Find the directions the arrows are pointing
signx = (x1-x0)/abs(x1-x0) if x1!=x0 else +1 #verify this once
signy = (y1-y0)/abs(y1-y0) if y1!=y0 else +1 #verified
# Append first arrowhead
dx = arrowLength * math.sin(math.radians(eta + arrowAngle))
dy = arrowLength * math.cos(math.radians(eta + arrowAngle))
edge_x.append(pointx)
edge_x.append(pointx - signx**2 * signy * dx)
edge_x.append(None)
edge_y.append(pointy)
edge_y.append(pointy - signx**2 * signy * dy)
edge_y.append(None)
# And second arrowhead
dx = arrowLength * math.sin(math.radians(eta - arrowAngle))
dy = arrowLength * math.cos(math.radians(eta - arrowAngle))
edge_x.append(pointx)
edge_x.append(pointx - signx**2 * signy * dx)
edge_x.append(None)
edge_y.append(pointy)
edge_y.append(pointy - signx**2 * signy * dy)
edge_y.append(None)
return edge_x, edge_y
# Packages import
import networkx as nx
import plotly.graph_objs as go
# Your input data
node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}
# General controls on the figure
NODE_SIZE = 46
LINE_WIDTH = 0.5
LINE_COLOR = '#888888'
FONT_FAMILY = 'serif'
# Create DiGraph
G=nx.DiGraph()
# Add nodes and edges
G.add_nodes_from(list(node_labels.keys()), weight=15)
G.add_edges_from(list(edge_labels.keys()))
# Create Positions
pos = nx.planar_layout(G) # nx.random_layout(G), ...
pos[4][0] = -0.7 # <-- Changing the position of node 4 for readability
pos[9][0] = 0.9 # <-- Changing the position of node 9 for readability
for node in G.nodes:
G.nodes[node]['pos'] = list(pos[node])
# Create Plot
# Create edges for plot and edge annotations
edge_x = []
edge_y = []
edge_label_x = []
edge_label_y = []
for edge in G.edges:
start = G.nodes[edge[0]]['pos']
end = G.nodes[edge[1]]['pos']
edge_label_x.append((start[0]+end[0])/2)
edge_label_y.append((start[1]+end[1])/2)
edge_x, edge_y = addEdge(start, end, edge_x, edge_y, .95, 'end', .03, 20, NODE_SIZE)
# Make go.Scatter for edges
edge_trace = go.Scatter(
x=edge_x, y=edge_y,
mode='lines',
line=dict(width=LINE_WIDTH, color=LINE_COLOR),
hoverinfo='none',
)
# Create nodes for plot
node_x = []
node_y = []
node_color = []
for node in G.nodes:
x, y = G.nodes[node]['pos']
node_x.append(x)
node_y.append(y)
node_color.append(color_map[node])
# Make go.Scatter for nodes
node_trace = go.Scatter(
x=node_x, y=node_y,
mode='markers+text',
hoverinfo='text',
text=list(node_labels.values()),
textposition="middle center", # ['top left', 'top center', 'top right', 'middle left',
# 'middle center', 'middle right', 'bottom left',
# 'bottom center', 'bottom right']
textfont=dict(
family=FONT_FAMILY,
size=10,
color="black"
),
marker=dict(
showscale=False,
color=node_color,
size=NODE_SIZE,
line_width=1
)
)
# Make edge annotations
edge_annotations = []
for label, x, y in zip(list(edge_labels.values()), edge_label_x, edge_label_y):
edge_annotations.append(
dict(
x=x, y=y,
showarrow=False,
hovertext='none',
ax=0,
ay=0,
bgcolor="white",
opacity=0.95,
text=label,
font=dict(
family=FONT_FAMILY,
size=14,
color="black",
)
)
)
# Make go.Figure
fig = go.Figure(
data=[edge_trace, node_trace],
layout=go.Layout(
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
title='<br>Network graph',
titlefont_size=16,
showlegend=False,
hovermode='closest',
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
autosize=False,
width=700,
height=700,
margin=dict(l=50, r=50, b=100, t=100, pad=4),
)
)
# Add edge annotations to go.Figure
for edge_annotation in edge_annotations:
fig.add_annotation(edge_annotation)
# Show go.Figure
fig.show()
导致:
默认情况下,iff 节点标签绘制在节点顶部(即没有偏移),netgraph 缩放节点标签字体大小,以便所有标签适合其各自的节点艺术家。但是,可以通过明确指定字体大小来覆盖此行为,例如使用 node_label_fontdict(size=20)
.
可以通过设置 edge_label_rotate = False
标志来关闭边缘标签的旋转。
#!/usr/bin/env python
# coding: utf-8
import matplotlib.pyplot as plt
import networkx as nx
from netgraph import Graph # pip install netgraph
node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}
graph = nx.from_edgelist(edge_labels, nx.DiGraph())
Graph(graph, node_layout='dot',
node_labels=node_labels, node_label_fontdict=dict(size=21),
edge_labels=edge_labels, edge_label_fontdict=dict(size=14), edge_label_rotate=False,
node_color=color_map, node_edge_color=color_map, arrows=True
)
plt.show()
我正在使用 netgraph 可视化我的 networkx 图。我现在的问题是,公式的可视化以自然的方式不如我预期的那么漂亮。这是我的示例图:
import networkx as nx
from netgraph import Graph # pip install netgraph
import matplotlib.pyplot as plt
node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}
graph = nx.from_edgelist(edge_labels, nx.DiGraph())
Graph(graph, node_labels=node_labels, edge_labels=edge_labels,
node_color=color_map, node_edge_color=color_map, arrows=True)
plt.show()
输出(直接/放大后):
我现在的问题:
- 他们是调整节点字体大小的方法吗?
- 是否可以旋转边缘标签使其水平对齐?
Plotly 有一个 very nice example of network graph 可以很容易地重新适应您的需要。
这是您的问题的答案。
# Packages import
import networkx as nx
import plotly.graph_objs as go
# Your input data
node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}
# Create DiGraph
G=nx.DiGraph()
# Add nodes and edges
G.add_nodes_from(list(node_labels.keys()), weight=15)
G.add_edges_from(list(edge_labels.keys()))
# Create Positions
pos = nx.planar_layout(G) # nx.random_layout(G), ...
# Create edges for plot and edge annotations
edge_x = []
edge_y = []
edge_label_x = []
edge_label_y = []
for edge in G.edges:
x0, y0 = pos[edge[0]][0], pos[edge[0]][1]
x1, y1 = pos[edge[1]][0], pos[edge[1]][1]
edge_x.append(x0)
edge_x.append(x1)
edge_x.append(None)
edge_y.append(y0)
edge_y.append(y1)
edge_y.append(None)
edge_label_x.append((x0+x1)/2)
edge_label_y.append((y0+y1)/2)
# Make go.Scatter for edges
edge_trace = go.Scatter(
x=edge_x, y=edge_y,
line=dict(width=0.5, color='#888'),
hoverinfo='none',
mode='lines'
)
# Create nodes for plot
node_x = []
node_y = []
node_color = []
for node in G.nodes:
x, y = pos[node][0], pos[node][1]
node_x.append(x)
node_y.append(y)
node_color.append(color_map[node])
# Make go.Scatter for nodes
node_trace = go.Scatter(
x=node_x, y=node_y,
mode='markers+text',
hoverinfo='text',
text=list(node_labels.values()),
textposition="middle center", # ['top left', 'top center', 'top right', 'middle left',
# 'middle center', 'middle right', 'bottom left',
# 'bottom center', 'bottom right']
textfont=dict(
family="sans serif",
size=10, # <-- Here you change the node text size
color="black"
),
marker=dict(
showscale=False,
color=node_color,
size=46,
line_width=1
)
)
# Make edge annotations
edge_annotations = []
for label, x, y in zip(list(edge_labels.values()), edge_label_x, edge_label_y):
edge_annotations.append(
dict(
x=x, y=y,
showarrow=False,
hovertext='none',
ax=0,
ay=0,
bgcolor="white",
opacity=0.85,
text=label,
font=dict(
family="sans serif",
size=14,
color="black",
)
)
)
# Make go.Figure
fig = go.Figure(
data=[edge_trace, node_trace],
layout=go.Layout(
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
title='<br>Network graph',
titlefont_size=16,
showlegend=False,
hovermode='closest',
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
autosize=False,
width=700,
height=700,
margin=dict(l=50, r=50, b=100, t=100, pad=4),
)
)
# Add edge annotations to go.Figure
for edge_annotation in edge_annotations:
fig.add_annotation(edge_annotation)
# Show go.Figure
fig.show()
导致:
编辑:
使用 Plotly 添加边缘方向有点棘手(
现在的代码是:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri May 15 11:45:07 2020
@author: aransil
"""
import math
# Start and end are lists defining start and end points
# Edge x and y are lists used to construct the graph
# arrowAngle and arrowLength define properties of the arrowhead
# arrowPos is None, 'middle' or 'end' based on where on the edge you want the arrow to appear
# arrowLength is the length of the arrowhead
# arrowAngle is the angle in degrees that the arrowhead makes with the edge
# dotSize is the plotly scatter dot size you are using (used to even out line spacing when you have a mix of edge lengths)
def addEdge(start, end, edge_x, edge_y, lengthFrac=1, arrowPos = None, arrowLength=0.025, arrowAngle = 30, dotSize=20):
# Get start and end cartesian coordinates
x0, y0 = start
x1, y1 = end
# Incorporate the fraction of this segment covered by a dot into total reduction
length = math.sqrt( (x1-x0)**2 + (y1-y0)**2 )
dotSizeConversion = .0565/20 # length units per dot size
convertedDotDiameter = dotSize * dotSizeConversion
lengthFracReduction = convertedDotDiameter / length
lengthFrac = lengthFrac - lengthFracReduction
# If the line segment should not cover the entire distance, get actual start and end coords
skipX = (x1-x0)*(1-lengthFrac)
skipY = (y1-y0)*(1-lengthFrac)
x0 = x0 + skipX/2
x1 = x1 - skipX/2
y0 = y0 + skipY/2
y1 = y1 - skipY/2
# Append line corresponding to the edge
edge_x.append(x0)
edge_x.append(x1)
edge_x.append(None) # Prevents a line being drawn from end of this edge to start of next edge
edge_y.append(y0)
edge_y.append(y1)
edge_y.append(None)
# Draw arrow
if not arrowPos == None:
# Find the point of the arrow; assume is at end unless told middle
pointx = x1
pointy = y1
eta = math.degrees(math.atan((x1-x0)/(y1-y0))) if y1!=y0 else 90.0
if arrowPos == 'middle' or arrowPos == 'mid':
pointx = x0 + (x1-x0)/2
pointy = y0 + (y1-y0)/2
# Find the directions the arrows are pointing
signx = (x1-x0)/abs(x1-x0) if x1!=x0 else +1 #verify this once
signy = (y1-y0)/abs(y1-y0) if y1!=y0 else +1 #verified
# Append first arrowhead
dx = arrowLength * math.sin(math.radians(eta + arrowAngle))
dy = arrowLength * math.cos(math.radians(eta + arrowAngle))
edge_x.append(pointx)
edge_x.append(pointx - signx**2 * signy * dx)
edge_x.append(None)
edge_y.append(pointy)
edge_y.append(pointy - signx**2 * signy * dy)
edge_y.append(None)
# And second arrowhead
dx = arrowLength * math.sin(math.radians(eta - arrowAngle))
dy = arrowLength * math.cos(math.radians(eta - arrowAngle))
edge_x.append(pointx)
edge_x.append(pointx - signx**2 * signy * dx)
edge_x.append(None)
edge_y.append(pointy)
edge_y.append(pointy - signx**2 * signy * dy)
edge_y.append(None)
return edge_x, edge_y
# Packages import
import networkx as nx
import plotly.graph_objs as go
# Your input data
node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}
# General controls on the figure
NODE_SIZE = 46
LINE_WIDTH = 0.5
LINE_COLOR = '#888888'
FONT_FAMILY = 'serif'
# Create DiGraph
G=nx.DiGraph()
# Add nodes and edges
G.add_nodes_from(list(node_labels.keys()), weight=15)
G.add_edges_from(list(edge_labels.keys()))
# Create Positions
pos = nx.planar_layout(G) # nx.random_layout(G), ...
pos[4][0] = -0.7 # <-- Changing the position of node 4 for readability
pos[9][0] = 0.9 # <-- Changing the position of node 9 for readability
for node in G.nodes:
G.nodes[node]['pos'] = list(pos[node])
# Create Plot
# Create edges for plot and edge annotations
edge_x = []
edge_y = []
edge_label_x = []
edge_label_y = []
for edge in G.edges:
start = G.nodes[edge[0]]['pos']
end = G.nodes[edge[1]]['pos']
edge_label_x.append((start[0]+end[0])/2)
edge_label_y.append((start[1]+end[1])/2)
edge_x, edge_y = addEdge(start, end, edge_x, edge_y, .95, 'end', .03, 20, NODE_SIZE)
# Make go.Scatter for edges
edge_trace = go.Scatter(
x=edge_x, y=edge_y,
mode='lines',
line=dict(width=LINE_WIDTH, color=LINE_COLOR),
hoverinfo='none',
)
# Create nodes for plot
node_x = []
node_y = []
node_color = []
for node in G.nodes:
x, y = G.nodes[node]['pos']
node_x.append(x)
node_y.append(y)
node_color.append(color_map[node])
# Make go.Scatter for nodes
node_trace = go.Scatter(
x=node_x, y=node_y,
mode='markers+text',
hoverinfo='text',
text=list(node_labels.values()),
textposition="middle center", # ['top left', 'top center', 'top right', 'middle left',
# 'middle center', 'middle right', 'bottom left',
# 'bottom center', 'bottom right']
textfont=dict(
family=FONT_FAMILY,
size=10,
color="black"
),
marker=dict(
showscale=False,
color=node_color,
size=NODE_SIZE,
line_width=1
)
)
# Make edge annotations
edge_annotations = []
for label, x, y in zip(list(edge_labels.values()), edge_label_x, edge_label_y):
edge_annotations.append(
dict(
x=x, y=y,
showarrow=False,
hovertext='none',
ax=0,
ay=0,
bgcolor="white",
opacity=0.95,
text=label,
font=dict(
family=FONT_FAMILY,
size=14,
color="black",
)
)
)
# Make go.Figure
fig = go.Figure(
data=[edge_trace, node_trace],
layout=go.Layout(
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
title='<br>Network graph',
titlefont_size=16,
showlegend=False,
hovermode='closest',
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
autosize=False,
width=700,
height=700,
margin=dict(l=50, r=50, b=100, t=100, pad=4),
)
)
# Add edge annotations to go.Figure
for edge_annotation in edge_annotations:
fig.add_annotation(edge_annotation)
# Show go.Figure
fig.show()
导致:
默认情况下,iff 节点标签绘制在节点顶部(即没有偏移),netgraph 缩放节点标签字体大小,以便所有标签适合其各自的节点艺术家。但是,可以通过明确指定字体大小来覆盖此行为,例如使用 node_label_fontdict(size=20)
.
可以通过设置 edge_label_rotate = False
标志来关闭边缘标签的旋转。
#!/usr/bin/env python
# coding: utf-8
import matplotlib.pyplot as plt
import networkx as nx
from netgraph import Graph # pip install netgraph
node_labels = {1: 'p→q', 2: '¬q', 3: '¬ (¬p)', 4: '¬p', 5: '¬p∧ ¬ (¬p)', 6: 'p', 7: 'q', 8: 'q∧ ¬q', 9: '¬p'}
color_map = {1: 'red', 2: 'red', 3: 'red', 4: 'red', 5: 'lightblue', 6: 'lightblue', 7: 'lightblue', 8: 'lightblue', 9: 'blue'}
edge_labels = {(3, 5): '∧I', (4, 5): '∧I', (4, 6): '¬E', (5, 6): '¬E', (1, 7): '→E', (6, 7): '→E', (2, 8): '∧I', (7, 8): '∧I', (8, 9): '¬E', (3, 9): '¬E'}
graph = nx.from_edgelist(edge_labels, nx.DiGraph())
Graph(graph, node_layout='dot',
node_labels=node_labels, node_label_fontdict=dict(size=21),
edge_labels=edge_labels, edge_label_fontdict=dict(size=14), edge_label_rotate=False,
node_color=color_map, node_edge_color=color_map, arrows=True
)
plt.show()