Python 3.x 如何用numpy计算单位向量的正交向量?

Python 3.x 如何用numpy计算单位向量的正交向量?,python-3.x,numpy,Python 3.x,Numpy,我在一个numpy数组u中有一组单位向量: import numpy as np a = np.arange(12).reshape(2,6) # generate some vectors u = a/np.linalg.norm(a, axis=0) # turn them into unit vectors print(u) [[0. 0.5547002 0.62469505 0.65079137 0.66436384 0.67267279] [1.

我在一个numpy数组u中有一组单位向量:

import numpy as np
a = np.arange(12).reshape(2,6)     # generate some vectors
u = a/np.linalg.norm(a, axis=0)    # turn them into unit vectors
print(u)
[[0.         0.5547002  0.62469505 0.65079137 0.66436384 0.67267279]
 [1.         0.83205029 0.78086881 0.7592566  0.74740932 0.73994007]]
现在我想通过翻转向量的分量,比如x,y->-y,x,来生成与每个向量正交的向量:

ortogonal_u = np.array(-u[1,:], u[0,:])
并获取错误

TypeError: data type not understood
我做错了什么?如何修复它


有没有更好的方法来找到这样一组向量的正交向量?我希望它能够执行。

您正在向数组构造函数传递两个数据参数,但它只需要一个。当传递第二个参数时,数组希望它是数组数据类型的描述,而u[0,:]不是有效的类型描述符

获得预期结果所需的最小更改是将两个切片放在一个列表中

np.array([-u[1,:], u[0,:]])

您正在向数组构造函数传递两个数据参数,但它只需要一个。当传递第二个参数时,数组希望它是数组数据类型的描述,而u[0,:]不是有效的类型描述符

获得预期结果所需的最小更改是将两个切片放在一个列表中

np.array([-u[1,:], u[0,:]])

您可以使用翻转和广播操作:

import numpy as np
a = np.arange(12).reshape(2,6)     # generate some vectors
u = a/np.linalg.norm(a, axis=0)    # turn them into unit vectors
print(u)

print(np.flip(u, axis=0) * np.array([[1], [-1]]))  # NEW LINE HERE

[[0.         0.14142136 0.24253563 0.31622777 0.37139068 0.41380294]
 [1.         0.98994949 0.9701425  0.9486833  0.92847669 0.91036648]]

[[ 1.          0.98994949  0.9701425   0.9486833   0.92847669  0.91036648]
 [-0.         -0.14142136 -0.24253563 -0.31622777 -0.37139068 -0.41380294]]

您可以使用翻转和广播操作:

import numpy as np
a = np.arange(12).reshape(2,6)     # generate some vectors
u = a/np.linalg.norm(a, axis=0)    # turn them into unit vectors
print(u)

print(np.flip(u, axis=0) * np.array([[1], [-1]]))  # NEW LINE HERE

[[0.         0.14142136 0.24253563 0.31622777 0.37139068 0.41380294]
 [1.         0.98994949 0.9701425  0.9486833  0.92847669 0.91036648]]

[[ 1.          0.98994949  0.9701425   0.9486833   0.92847669  0.91036648]
 [-0.         -0.14142136 -0.24253563 -0.31622777 -0.37139068 -0.41380294]]

如果您希望在大型阵列中快速执行此操作,它有助于在适当的位置执行操作。以下步骤可以做到这一点:

a = np.arange(12).reshape(2,6)

a = a[::-1, :]   # change the indexing to reverse the vector to swap x and y (note that this doesn't do any copying)
np.negative(a[0,:], out=a[0, :])  # negate one axis

#  [[ -6  -7  -8  -9 -10 -11]
#   [  0   1   2   3   4   5]]
快速测试此答案和其他一些张贴的答案:

N = 10000000
a0 = np.arange(2*N).reshape(2,N)

def f0(a):
    x = a[::-1, :]
    np.negative(x[0,:], out=x[10, :])
    return x

def f1(a):
    x = np.array([-a[1,:], a[0,:]])
    return x

def f2(a):
    x = np.flip(a, axis=0) * np.array([[1], [-1]])
    return x

%timeit f0(a0)
#   6.69 ms ± 81.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit f1(a0)
# 103 ms ± 1.41 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit f2(a0)
#  81.6 ms ± 1.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

因此,对于非常大的阵列,就地操作的速度要快10倍以上。这是特别快的,因为它所做的只是在数组头上的单个操作中改变索引方向,而不受数组大小的影响,然后改变一行的符号,所以这是一个不同寻常的速度增益。目前,我怀疑标志更改需要一份副本,但可能有一种方法可以在没有副本的情况下完成,但我不知道。另外,请注意,如果您在适当的位置执行操作,则原始阵列会被过度写入,因此这可能不适用于您的用例。

如果您希望在较大的阵列中快速执行此操作,则可以在适当的位置执行操作。以下步骤可以做到这一点:

a = np.arange(12).reshape(2,6)

a = a[::-1, :]   # change the indexing to reverse the vector to swap x and y (note that this doesn't do any copying)
np.negative(a[0,:], out=a[0, :])  # negate one axis

#  [[ -6  -7  -8  -9 -10 -11]
#   [  0   1   2   3   4   5]]
快速测试此答案和其他一些张贴的答案:

N = 10000000
a0 = np.arange(2*N).reshape(2,N)

def f0(a):
    x = a[::-1, :]
    np.negative(x[0,:], out=x[10, :])
    return x

def f1(a):
    x = np.array([-a[1,:], a[0,:]])
    return x

def f2(a):
    x = np.flip(a, axis=0) * np.array([[1], [-1]])
    return x

%timeit f0(a0)
#   6.69 ms ± 81.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit f1(a0)
# 103 ms ± 1.41 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit f2(a0)
#  81.6 ms ± 1.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
因此,对于非常大的阵列,就地操作的速度要快10倍以上。这是特别快的,因为它所做的只是在数组头上的单个操作中改变索引方向,而不受数组大小的影响,然后改变一行的符号,所以这是一个不同寻常的速度增益。目前,我怀疑标志更改需要一份副本,但可能有一种方法可以在没有副本的情况下完成,但我不知道。另外,请注意,如果您在适当的位置执行该操作,则原始数组被重写,因此这可能不适用于您的用例