【问题标题】:form numpy array from possible numpy array从可能的 numpy 数组中形成 numpy 数组
【发布时间】:2016-08-23 06:47:35
【问题描述】:

编辑

我意识到我没有很好地检查我的 mwe,因此问了一些错误的问题。主要问题是当 numpy 数组作为 2d 数组而不是 1d 传入时(或者甚至当 python 列表作为 1d 而不是 2d 传入时)。所以如果我们有

x = np.array([[1], [2], [3]]) 

那么显然,如果您尝试对此进行索引,那么您将获得数组(如果您使用 item,则不使用)。这同样适用于标准的 Python 列表。

很抱歉让您感到困惑。

原创

我正在尝试从可能是 numpy 数组或标准 python 列表的东西中形成一个新的 numpy 数组。

例如

import numpy as np

x = [2, 3, 1]

y = np.array([[0, -x[2], x[1]], [x[2], 0, -x[0]], [-x[1], x[0], 0]])

现在我想形成一个函数,以便我可以轻松地制作y

def skew(vector):
    """
    this function returns a numpy array with the skew symmetric cross product matrix for vector.
    the skew symmetric cross product matrix is defined such that
    np.cross(a, b) = np.dot(skew(a), b)

    :param vector: An array like vector to create the skew symmetric cross product matrix for
    :return: A numpy array of the skew symmetric cross product vector
    """

    return np.array([[0, -vector[2], vector[1]], 
                     [vector[2], 0, -vector[0]], 
                     [-vector[1], vector[0], 0]])

这很好用,我现在可以写了(假设包含上述函数)

import numpy as np

x=[2, 3, 1]

y = skew(x)

但是,我还希望能够在现有的 1d 或 2d numpy 数组上调用 skew。比如

import numpy as np

x = np.array([2, 3, 1])

y = skew(x)

不幸的是,这样做会返回一个 numpy 数组,其中的元素也是 numpy 数组,而不是我想要的 python 浮点数。

有没有一种简单的方法来形成一个新的 numpy 数组,就像我从 python 列表或 numpy 数组中所做的那样,结果只是一个标准的 numpy 数组,每个元素中都有浮点数?

现在显然一种解决方案是检查输入是否为 numpy 数组:

def skew(vector):
    """
    this function returns a numpy array with the skew symmetric cross product matrix for vector.
    the skew symmetric cross product matrix is defined such that
    np.cross(a, b) = np.dot(skew(a), b)

    :param vector: An array like vector to create the skew symmetric cross product matrix for
    :return: A numpy array of the skew symmetric cross product vector
    """
    if isinstance(vector, np.ndarray):
        return np.array([[0, -vector.item(2), vector.item(1)],
                         [vector.item(2), 0, -vector.item(0)],
                         [-vector.item(1), vector.item(0), 0]])
    else:
        return np.array([[0, -vector[2], vector[1]], 
                         [vector[2], 0, -vector[0]], 
                         [-vector[1], vector[0], 0]])

但是,不得不到处编写这些实例检查变得非常乏味。

另一种解决方案是先将所有内容转换为数组,然后使用数组调用

def skew(vector):
    """
    this function returns a numpy array with the skew symmetric cross product matrix for vector.
    the skew symmetric cross product matrix is defined such that
    np.cross(a, b) = np.dot(skew(a), b)

    :param vector: An array like vector to create the skew symmetric cross product matrix for
    :return: A numpy array of the skew symmetric cross product vector
    """

    vector = np.array(vector)

    return np.array([[0, -vector.item(2), vector.item(1)],
                     [vector.item(2), 0, -vector.item(0)],
                     [-vector.item(1), vector.item(0), 0]])

但我觉得这效率低下,因为它需要创建一个新的向量副本(在这种情况下没什么大不了的,因为向量很小,但这只是一个简单的例子)。

我的问题是,除了我所讨论的内容之外,是否有其他方法可以做到这一点,或者我是否坚持使用其中一种方法?

【问题讨论】:

  • 您使用的是哪个 numpy 版本?对于 numpy 1.10.4,从数组中获取单个元素会返回标量而不是 numpy 数组,因此您的初始函数可以按照您的意愿工作。
  • 我使用的是 1.10.4 @MSeifert,但是我在问题中犯了一个错误。主要问题是我使用二维数组来模拟列向量。我会解决这个问题。

标签: python arrays numpy


【解决方案1】:

您可以使用numpy.asarray() 有效地实现最后一个想法:

vector = np.asarray(vector)

那么,如果 vector 已经是 NumPy 数组,则不会发生复制。

【讨论】:

    【解决方案2】:

    您可以保留函数的第一个版本并将numpy数组转换为list

    def skew(vector):
    
        if isinstance(vector, np.ndarray):
            vector = vector.tolist()
    
        return np.array([[0, -vector[2], vector[1]], 
                         [vector[2], 0, -vector[0]], 
                         [-vector[1], vector[0], 0]])
    
    In [58]: skew([2, 3, 1])
    Out[58]:
    array([[ 0, -1,  3],
           [ 1,  0, -2],
           [-3,  2,  0]])
    
    In [59]: skew(np.array([2, 3, 1]))
    Out[59]:
    array([[ 0, -1,  3],
           [ 1,  0, -2],
           [-3,  2,  0]])
    

    【讨论】:

      【解决方案3】:

      这不是最佳解决方案,但非常简单。 您可以默认将向量转换为列表。

      def skew(vector): 
          vector = list(vector)
          return np.array([[0, -vector[2], vector[1]], 
                           [vector[2], 0, -vector[0]], 
                           [-vector[1], vector[0], 0]])
      

      【讨论】:

      • 如果vector已经是一个列表,你知道list是否会创建一个副本吗?下面的@John Zwinck 似乎暗示如果内部已经是一个看起来至少效率更高的数组,则 asarray 不会复制。
      • 考虑到我在几分钟前给出了这个答案,你能解释一下你的问题的附加价值吗?
      • 你指的是我@ColonelBeauvel?
      • 对不起,我还没有看到你的答案,我已经在写我的了。但是,我的方法不那么罗嗦,我不确定调用 isinstance() 会增加更多...
      • .tolist() 如果数组可能是 2d 更好。
      【解决方案4】:

      数组是可迭代的。你可以在你的 skew 函数中写:

      def skew(x):
          return np.array([[0, -x[2], x[1]],
                           [x[2], 0, -x[0]],
                           [-x[1], x[0], 0]])
      x = [1,2,3]
      y = np.array([1,2,3])
      >>> skew(y)
      array([[ 0, -3,  2],
             [ 3,  0, -1],
             [-2,  1,  0]])
      >>> skew(x)
      array([[ 0, -3,  2],
             [ 3,  0, -1],
             [-2,  1,  0]])
      

      在任何情况下,您的方法都以包含浮点数的 numpy 数组的一维元素结束。在任何情况下,您都需要调用二维来获取浮动。

      关于您在 cmets 中告诉我的内容,您可以为二维数组添加 if 条件:

      def skew(x):
           if (isinstance(x,ndarray) and len(x.shape)>=2):
               return np.array([[0, -x[2][0], x[1][0]],
                                [x[2][0], 0, -x[0][0]],
                                [-x[1][0], x[0][0], 0]])
           else:
               return np.array([[0, -x[2], x[1]],
                                [x[2], 0, -x[0]],
                                [-x[1], x[0], 0]])
      

      【讨论】:

      • 一维数组很容易迭代是的,但是,二维数组更复杂。例如,如果x=np.array([[1], [2], [3]]) 则上述方法将不起作用(我通常将我的数组保留为 2d 以模拟列向量)。抱歉,我的问题不清楚。我会解决这个问题
      • 所以我现在意识到最好的选择是使用x[1][0] 进行索引,因为这将始终适用于最多二维数组或列表而无需复制。您能否更新您的答案以反映这一点,然后我会接受?
      • 对于 numpy 数组,您可以检查 'vector.shape' 方法的长度(2d 数组为 2)。对于嵌套列表,它可能会变得更加棘手。
      • 感谢您进行更新。我认为你甚至不需要走那么远。无论x 是1d 还是2d,都可以很容易地写出np.array([[0, x[2][0], x[1][0]],...
      猜你喜欢
      • 1970-01-01
      • 2022-01-16
      • 2017-03-12
      • 1970-01-01
      • 2020-08-08
      • 2021-02-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多