如何使用Python绘制图表?

huangapple go评论75阅读模式
英文:

How to draw a graph with python?

问题

我需要程序绘制一个类似图片中的图形。如何将正方形分成四部分?如何在箭头上写字?
如何使用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?
如何使用Python绘制图表?

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补丁、arrowtext函数来构建你想要的网络。

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()

这相对复杂,可能有使用NetworkXETEToolkit(在评论中建议的方式)更简单的方法。个人而言,我会在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()

如何使用Python绘制图表?

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).

huangapple
  • 本文由 发表于 2023年5月22日 15:25:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76303854.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定