英文:
How to draw a graph with python?
问题
我需要程序绘制一个类似图片中的图形。如何将正方形分成四部分?如何在箭头上写字?
我尝试制作一个圆形图,但不幸的是它不允许将圆分成四部分。
英文:
I need the program to draw a graph like the one in the picture. How to make the square into four parts? How to write text on the arrows?
I tried to make a circular graph, but unfortunately it didn't work because it doesn't allow to divide the circle into four parts
答案1
得分: 1
我已经翻译好你提供的文本,以下是翻译结果:
我将这个作为评论发布在你的另一个问题中,但这里有一个示例,开始使用Matplotlib的Rectangle
补丁、arrow
和text
函数来构建你想要的网络。
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.patches import Rectangle
fig, ax = plt.subplots()
def draw_2x2_grid(ax, xy, bwidth=0.25, bheight=0.25, numbers=[]):
"""
在每个框中绘制带有数字的2x2方格。
"""
for i in range(2):
x = xy[0] + i * bwidth
for j in range(2):
y = xy[1] + j * bheight
r = Rectangle((x, y), bwidth, bheight, facecolor="none", edgecolor="k", lw=3)
ax.add_patch(r)
ax.text(
x + bwidth / 2,
y + bheight / 2,
str(numbers[i * 2 + j]),
va="center",
ha="center",
fontsize=20,
)
def draw_arrow(ax, xystart, xyend, textabove=None, textbelow=None, arrowkwargs={}):
"""
在两个点之间绘制并注释箭头。
"""
# 获取位移 dx, dy
dx = xyend[0] - xystart[0]
dy = xyend[1] - xystart[1]
angle = np.rad2deg(np.arctan2(dy, dx))
ax.arrow(xystart[0], xystart[1], dx, dy, **arrowkwargs)
# 添加文本
if textabove is not None:
ax.text(
xystart[0] + dx / 2,
xystart[1] + dy / 2,
textabove,
ha="center",
va="bottom",
transform_rotates_text=True,
rotation=angle,
rotation_mode='anchor',
fontsize=12,
)
if textbelow is not None:
ax.text(
xystart[0] + dx / 2,
xystart[1] + dy / 2,
textbelow,
ha="center",
va="top",
transform_rotates_text=True,
rotation=angle,
rotation_mode='anchor',
fontsize=12,
)
# 2x2网格内每个子框的宽度和高度
bwidth = 0.3
bheight = 0.3
# 每个框的左下角 x、y 位置
boxpositions = [
(0, 0),
(0 + 3.5 * bwidth, 0 - 3 * bheight),
(0 + 3.5 * bwidth, 0 + 2 * bheight),
]
# 框内的数字
boxnumbers = [
[0, 1, 0, 0],
[2, 3, 2, 0],
[1, 2, 2, 1],
]
# 绘制框
for bpos, bnum in zip(boxpositions, boxnumbers):
draw_2x2_grid(ax, bpos, bwidth=bwidth, bheight=bheight, numbers=bnum)
# 绘制箭头
draw_arrow(
ax,
(boxpositions[0][0] + 2 * bwidth, boxpositions[0][1] + bheight),
(boxpositions[1][0], boxpositions[1][1] + bheight),
textbelow="$t = 2$",
textabove="$a_2(0)$",
arrowkwargs={"color": "r", "head_width": 0.05, "length_includes_head": True, "lw": 2},
)
draw_arrow(
ax,
(boxpositions[0][0] + 2 * bwidth, boxpositions[0][1] + bheight),
(boxpositions[2][0], boxpositions[2][1] + bheight),
textbelow="$t = 1$",
textabove="$a_1(1)$",
arrowkwargs={"color": "k", "head_width": 0.05, "length_includes_head": True, "lw": 2},
)
ax.axis("equal")
ax.set_axis_off()
fig.show()
这相对复杂,可能有使用NetworkX或ETEToolkit(在评论中建议的方式)更简单的方法。个人而言,我会在PowerPoint(或类似工具)中创建类似的图表。
英文:
I posted this as a comment in your other question, but here's an example that starts building up the network that you picture using Matplotlib's Rectangle
patch, arrow
and text
functions which you can then build up from.
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.patches import Rectangle
fig, ax = plt.subplots()
def draw_2x2_grid(ax, xy, bwidth=0.25, bheight=0.25, numbers=[]):
"""
Draw a 2x2 grid of squares with numbers in each box.
"""
for i in range(2):
x = xy[0] + i * bwidth
for j in range(2):
y = xy[1] + j * bheight
r = Rectangle((x, y), bwidth, bheight, facecolor="none", edgecolor="k", lw=3)
ax.add_patch(r)
ax.text(
x + bwidth / 2,
y + bheight / 2,
str(numbers[i * 2 + j]),
va="center",
ha="center",
fontsize=20,
)
def draw_arrow(ax, xystart, xyend, textabove=None, textbelow=None, arrowkwargs={}):
"""
Draw and annotate an arrow between two points.
"""
# get displacements dx, dy
dx = xyend[0] - xystart[0]
dy = xyend[1] - xystart[1]
angle = np.rad2deg(np.arctan2(dy, dx))
ax.arrow(xystart[0], xystart[1], dx, dy, **arrowkwargs)
# add text
if textabove is not None:
ax.text(
xystart[0] + dx / 2,
xystart[1] + dy / 2,
textabove,
ha="center",
va="bottom",
transform_rotates_text=True,
rotation=angle,
rotation_mode='anchor',
fontsize=12,
)
if textbelow is not None:
ax.text(
xystart[0] + dx / 2,
xystart[1] + dy / 2,
textbelow,
ha="center",
va="top",
transform_rotates_text=True,
rotation=angle,
rotation_mode='anchor',
fontsize=12,
)
# width and height of each subbox within a 2x2 grid
bwidth = 0.3
bheight = 0.3
# bottom left x, y positions of boxes
boxpositions = [
(0, 0),
(0 + 3.5 * bwidth, 0 - 3 * bheight),
(0 + 3.5 * bwidth, 0 + 2 * bheight),
]
# numbers in boxes
boxnumbers = [
[0, 1, 0, 0],
[2, 3, 2, 0],
[1, 2, 2, 1],
]
# draw boxes
for bpos, bnum in zip(boxpositions, boxnumbers):
draw_2x2_grid(ax, bpos, bwidth=bwidth, bheight=bheight, numbers=bnum)
# draw arrows
draw_arrow(
ax,
(boxpositions[0][0] + 2 * bwidth, boxpositions[0][1] + bheight),
(boxpositions[1][0], boxpositions[1][1] + bheight),
textbelow="$t = 2$",
textabove="$a_2(0)$",
arrowkwargs={"color": "r", "head_width": 0.05, "length_includes_head": True, "lw": 2},
)
draw_arrow(
ax,
(boxpositions[0][0] + 2 * bwidth, boxpositions[0][1] + bheight),
(boxpositions[2][0], boxpositions[2][1] + bheight),
textbelow="$t = 1$",
textabove="$a_1(1)$",
arrowkwargs={"color": "k", "head_width": 0.05, "length_includes_head": True, "lw": 2},
)
ax.axis("equal")
ax.set_axis_off()
fig.show()
This is relatively complicated and there may be easier ways with NetworkX or the ETEToolkit (as suggested in the comments). Personally, I'd just make a plot like that in PowerPoint (or equivalent).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论