使用 matplotlib 绘制给定笛卡尔坐标的路径

Using matplotlib to draw a path given cartesian coordinates

我是 matplotlib 和 numpy 的新手,我正在尝试将一些数组数据绘制成如下所示:

但目前看起来像这样:

我的代码非常基础,但基本上上图是我希望能够做到的。我不太关心绘制网格线,但情节应该成比例。我看过 mathplotlib 网站上的一些例子,但找不到足够相似的东西。 我想知道是不是 pyplot 程序不正确或者我的数组格式不正确?

import numpy as np
from matplotlib import pyplot as plt

data = [(2, 2), (3, 2), (4, 1), (4, 0), (3, 0), (3, 1), (4, 2),
        (4, 3), (4, 4), (3, 3), (3, 4), (2, 4), (2, 3), (1, 4),
        (0, 4), (0, 3), (1, 3), (0, 2), (1, 2), (0, 1), (0, 0),
        (1, 0), (1, 1), (2, 0), (2, 1)]

data = np.asarray(data)
print(data)
plt.ylim(0, 4)
plt.xlim(0, 4)
plt.axis([0, 4, 0, 4])
plt.plot(data)
plt.show()

尝试

plt.plot(*data.transpose())

而不是

plt.plot(data)

plt.plot 函数采用 2 个数组,一个包含所有 x-values,一个包含所有 y-values。您不能将 x 和 y 值的混合传递给它。 transpose 方法将对值重新排序,以便所有 x 值在一起并且所有 y 值在一起并且星号 * 运算符会将这些数组解压缩到两个单独的函数参数中。

您可以尝试这样的操作:

import numpy as np
from matplotlib import pyplot as plt

data = [(2, 2), (3, 2), (4, 1), (4, 0), (3, 0), (3, 1), (4, 2),
        (4, 3), (4, 4), (3, 3), (3, 4), (2, 4), (2, 3), (1, 4),
        (0, 4), (0, 3), (1, 3), (0, 2), (1, 2), (0, 1), (0, 0),
        (1, 0), (1, 1), (2, 0), (2, 1)]

for i in range(len(data) -1): 
  x1 = data[i][0]
  y1 = data[i][1]
  x2 = data[i+1][0]
  y2 = data[i+1][1]
  plt.plot([x1, x2], [y1, y2], c='blue')
  plt.scatter(x1, y1, c='blue')
plt.show()

您需要像这样将 x 和 y 分量解压缩到数组中:

plt.plot([p[0] for p in data], [p[1] for p in data], 'o-')

使用格式样式"o-":“o”表示符号标记,“-”表示实线。

要同时格式化 x/y 刻度,这里是完整代码:

from matplotlib import pyplot as plt

data = [(2, 2), (3, 2), (4, 1), (4, 0), (3, 0), (3, 1), (4, 2),
        (4, 3), (4, 4), (3, 3), (3, 4), (2, 4), (2, 3), (1, 4),
        (0, 4), (0, 3), (1, 3), (0, 2), (1, 2), (0, 1), (0, 0),
        (1, 0), (1, 1), (2, 0), (2, 1)]

x = [p[0] for p in data]
y = [p[1] for p in data]
_, ax = plt.subplots()
ax.set_xticks(range(5))
ax.set_yticks(range(5))
ax.plot(x, y, 'o-', color='blue')
plt.grid() # add grid lines
plt.show()

输出:

为了完成其他答案,这里是我在合理的时间内得到的最接近您所需输出的答案:

import numpy as np
from matplotlib import pyplot as plt

data = [(2, 2), (3, 2), (4, 1), (4, 0), (3, 0), (3, 1), (4, 2),
        (4, 3), (4, 4), (3, 3), (3, 4), (2, 4), (2, 3), (1, 4),
        (0, 4), (0, 3), (1, 3), (0, 2), (1, 2), (0, 1), (0, 0),
        (1, 0), (1, 1), (2, 0), (2, 1)]

data = np.asarray(data)
print(data)

# make axis equal and turn them off
plt.axis('equal')
plt.axis('off')

for i in range(5):
    # horizontal and vertical background lines
    plt.plot([i,i], [0,4], linewidth=0.5, color='black')
    plt.plot([0,4], [i,i], linewidth=0.5, color='black')
plt.plot(data[:,0], data[:,1], 'b') # line segments
plt.scatter(data[:,0], data[:,1], c='b') # markers

plt.show()

输出:


编辑

this question 开始,您可以通过 plt.annotate 在每个标记处添加数字。只需在 plt.scatter 之后添加:

offset = np.array([0.1, 0.1])
for i in range(data.shape[0]):
    # For each marker
    plt.annotate(str(i+1), data[i]+offset)

输出:


编辑#2:

作为奖励,这是我尽可能接近参考图的尝试:

import numpy as np
from matplotlib import pyplot as plt

data = [(2, 2), (3, 2), (4, 1), (4, 0), (3, 0), (3, 1), (4, 2),
        (4, 3), (4, 4), (3, 3), (3, 4), (2, 4), (2, 3), (1, 4),
        (0, 4), (0, 3), (1, 3), (0, 2), (1, 2), (0, 1), (0, 0),
        (1, 0), (1, 1), (2, 0), (2, 1)]

data = np.asarray(data)
print(data)

# make axis equal and turn them off
plt.axis('equal')
plt.axis('off')

for i in range(5):
    # horizontal and vertical background lines
    plt.plot([i,i], [0,4], linewidth=1.5, color='#b3b3b3', zorder=1)
    plt.plot([0,4], [i,i], linewidth=1.5, color='#b3b3b3', zorder=1)

plt.plot(data[:,0], data[:,1], '#274b8b', linewidth=2.5, zorder=2) # line segments
plt.scatter(data[np.arange(len(data))!=7,0], data[np.arange(len(data))!=7,1], s=60, c='#4472c4', edgecolors='#2e569c', zorder=3) # markers
# marker for point 7 is not plotted in reference figure

# Individual points numbers, not in reference figure so commented
# offset = np.array([0.1, 0.1])
# for i in range(data.shape[0]):
    # # For each marker
    # plt.annotate(str(i+1), data[i]+offset)

for i in range(5):
    plt.annotate(str(i), [i-0.05, -0.25]) # X axis numbers
    plt.annotate(str(i), [-0.2, i-0.07]) # Y axis numbers


plt.show()