首页 > 解决方案 > 如何生成如下矩阵?

问题描述

所以给定 numbern和一个数组a,我们需要创建一个nbylen(a)矩阵,其中矩阵的i,j第 th 项是1ifi等于jth 项,a否则-1i即对于从0到的每个数字n-1,我们需要一个数组来告诉我们该数字i是否等于该数组a

如果我们有像函数式编程那样的地图功能,那就太酷了。然后我可以通过检查数组中的每个元素a是否等于给定数字来创建行。

那么有没有我可以使用的功能,如下所示?

result=[]
for i in range(n):
    result=np.vstack(result, np.map(checkequals(x,i),a)
return result

标签: pythonnumpy

解决方案


通常,函数或映射方法不是最佳的numpynumpy都是关于数组的,所以最好从提供的整个数组构建块的角度来考虑numpy。那些在编译代码中运行。

例如你的情况:

定义一个数组:

In [10]: a = np.random.randint(0,10,9)                                          
In [11]: a                                                                      
Out[11]: array([6, 0, 2, 5, 0, 5, 2, 0, 1])

将其与值的范围进行比较n- 使用整个数组==测试(和broadcasting。结果是一个布尔数组,每个 (i,j) 的真/假值:

In [12]: np.arange(8)[:,None]==a                                                
Out[12]: 
array([[False,  True, False, False,  True, False, False,  True, False],
       [False, False, False, False, False, False, False, False,  True],
       [False, False,  True, False, False, False,  True, False, False],
       [False, False, False, False, False, False, False, False, False],
       [False, False, False, False, False, False, False, False, False],
       [False, False, False,  True, False,  True, False, False, False],
       [ True, False, False, False, False, False, False, False, False],
       [False, False, False, False, False, False, False, False, False]])

鉴于此,很容易将其映射到 (-1,1) 值。 np.where只是这样一种方式:

In [13]: np.where(np.arange(8)[:,None]==a, 1, -1)                               
Out[13]: 
array([[-1,  1, -1, -1,  1, -1, -1,  1, -1],
       [-1, -1, -1, -1, -1, -1, -1, -1,  1],
       [-1, -1,  1, -1, -1, -1,  1, -1, -1],
       [-1, -1, -1, -1, -1, -1, -1, -1, -1],
       [-1, -1, -1, -1, -1, -1, -1, -1, -1],
       [-1, -1, -1,  1, -1,  1, -1, -1, -1],
       [ 1, -1, -1, -1, -1, -1, -1, -1, -1],
       [-1, -1, -1, -1, -1, -1, -1, -1, -1]])

更接近您的地图想法,我们可以定义一个对一对标量值进行操作的函数:

def foo(i,x):
    if i==x:
        return 1
    else:
        return -1

并用于np.vectorize制作一个需要 2 个数组的函数,并将成对的标量传递给该函数。

In [16]: np.vectorize(foo)(np.arange(8)[:,None], a)                              
Out[16]: 
array([[-1,  1, -1, -1,  1, -1, -1,  1, -1],
       [-1, -1, -1, -1, -1, -1, -1, -1,  1],
       [-1, -1,  1, -1, -1, -1,  1, -1, -1],
       [-1, -1, -1, -1, -1, -1, -1, -1, -1],
       [-1, -1, -1, -1, -1, -1, -1, -1, -1],
       [-1, -1, -1,  1, -1,  1, -1, -1, -1],
       [ 1, -1, -1, -1, -1, -1, -1, -1, -1],
       [-1, -1, -1, -1, -1, -1, -1, -1, -1]])

但这比第一种方法慢得多。

列表理解方法:

In [22]: [[(1 if i==x else -1) for x in a] for i in range(8)]                   
Out[22]: 
[[-1, 1, -1, -1, 1, -1, -1, 1, -1],
 [-1, -1, -1, -1, -1, -1, -1, -1, 1],
 [-1, -1, 1, -1, -1, -1, 1, -1, -1],
 [-1, -1, -1, -1, -1, -1, -1, -1, -1],
 [-1, -1, -1, -1, -1, -1, -1, -1, -1],
 [-1, -1, -1, 1, -1, 1, -1, -1, -1],
 [1, -1, -1, -1, -1, -1, -1, -1, -1],
 [-1, -1, -1, -1, -1, -1, -1, -1, -1]]

然后可以将其制成一个数组(这实际上可能比该vectorize方法更快)。


推荐阅读