【问题标题】:List of simple arrays with pyplot.plot带有 pyplot.plot 的简单数组列表
【发布时间】:2018-01-07 13:45:36
【问题描述】:

我很难理解pyplot.plot 的工作原理。
我举一个简单的例子:我想绘制pyplot.plot(lst2, lst2),其中 lst2 是一个列表。
困难在于 lst2 的每个元素都是一个形状为 (1,1) 的数组。如果元素是浮动的而不是数组,就没有问题。

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

V2 = np.array([[1]])
W2 = np.array([[2]])

print('The shape of V2 is', V2.shape)
print('The shape of W2 is', W2.shape)

lst2 = [V2, W2]
plt.plot(lst2, lst2)
plt.show

以下是我收到的错误消息的结尾:

~\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _xy_from_xy(self,x, y)
    245         if x.ndim > 2 or y.ndim > 2:
    246             raise ValueError("x and y can be no greater than 2-D, but have "
--> 247                              "shapes {} and {}".format(x.shape, y.shape))
    248 
    249         if x.ndim == 1:

ValueError: x and y can be no greater than 2-D, but have shapes (2, 1, 1) and (2, 1, 1)

错误消息中让我惊讶的是提到了一个维度为 (2,1,1) 的数组。看起来数组np.array([V2,W2]) 是在我们调用pyplot.plot 时构建的。

我的问题是,当我们使用 x 和 y 列表调用 pyplot.plot(x,y) 时,幕后会发生什么?似乎构建了一个包含 x 元素的数组(对于 y 也是如此)。并且这些数组必须有最大 2 个轴。我对么?

我知道如果我在 V2 和 W2 上使用 numpy.squeeze,它会起作用。但我想了解在我给出的示例中pyplot.plot 内部发生了什么。

【问题讨论】:

    标签: python arrays numpy matplotlib plot


    【解决方案1】:

    仔细看看你在做什么:

    V2 = np.array([[1]])
    W2 = np.array([[2]])
    lst2 = [V2, W2]
    plt.plot(lst2, lst2)
    

    出于某种奇怪的原因,您使用一对嵌套的括号将数组定义为(1,1) 的形状。当您构造lst2 时,您将沿新的前导维度 堆叠数组。这和pyplot无关,这是numpy。

    Numpy 数组是矩形的,它们与列表列表的列表兼容。嵌套级别决定了数组的维数。看一个简单的 2d 示例:

    >>> M = np.arange(2*3).reshape(2,3)
    >>> print(repr(M))
    array([[0, 1, 2],
           [3, 4, 5]])
    

    您可以将这个 2x3 矩阵视为两个行向量。 M[0]M[0,:] 相同,为第一行,M[1]M[1,:] 相同,为第二行。然后,您还可以通过以下方式从两行构造此数组:

    row1 = [0, 1, 2]
    row2 = [3, 4, 5]
    lst = [row1, row2]
    np.array(lst)
    

    我的意思是,我们采用了两个长度为 3 的平面列表(与形状为 (3,) 的一维 numpy 数组兼容),并将它们连接到一个列表中。结果与形状为(2,3) 的二维数组兼容。 “2”是因为我们将 2 个列表放入 lst,而“3”是因为两个列表的长度都是 3。

    因此,当您在上面创建lst2 时,您正在做的事情与此等价:

    lst2 = [ [[1]], [[2]] ]
    

    您将两个嵌套的子列表放入一个数组兼容列表中,并且两个子列表都与形状(1,1) 兼容。这意味着您最终将得到一个 3d 数组(根据您在嵌套最深级别有三个左括号的事实),形状为 (2,1,1)。再次,2 来自你有两个数组的事实,尾随维度来自内容。


    真正的问题是你想要做什么。一方面,您的数据不应该是真正的形状 (1,1)。在pyplot.plot 最直接的应用程序中,您拥有一维数据集:一个用于 x 坐标,一个用于绘图的 y 坐标。为此,您可以对 x 和 y 使用简单(平面)列表或一维数组。重要的是它们的长度相同。

    然后,当您将两者相互绘制时,首先传递 x 坐标,然后传递 y 坐标。你大概的意思是

    plt.plot(V2,W2)
    

    在这种情况下,您将传递二维数组进行绘图,并且您不会看到传递类似 3d 数组的错误。但是,pyplot.plot 的行为对于 2d 输入而言并非微不足道(两个数据集的列将相互绘制),并且您必须确保您确实想要将 2d 数组作为输入传递。但是您几乎不想将与前两个参数相同的对象传递给pyplot.plot

    【讨论】:

    • 我问这个问题的原因是因为当您使用形状为 (1,n) 的 A 和形状为 (n,1) 的 B 执行 np.dot (A,B) 时,您会得到一个形状 (1,1) 的数组,不幸的是不是一个浮动的。我正在做一个循环,对于每次迭代,我都在计算这种矩阵乘积,并将结果放在带有函数 append 的列表的末尾。最后,我有一个形状列表 (number_iter, 1,1),而不是一个简单的浮动列表。而且我无法绘制列表。
    • @S.Tim 感谢您的反馈。您可能不应该从那些“线性二维数组”开始。你在使用np.matrix 类吗?您应该改用ndarrays,它们更方便。是否有可能并行计算每次迭代?在这种情况下,您可以比循环做得更好(在性能方面),您可以一次计算所有点积。
    猜你喜欢
    • 2023-03-25
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-30
    相关资源
    最近更新 更多