【问题标题】:Create a matrix from a function从函数创建矩阵
【发布时间】:2019-09-15 19:34:26
【问题描述】:

我想从一个函数创建一个矩阵,如果行索引小于给定阈值 k,则 (3,3) 矩阵 C 的值等于 1。

import numpy as np

k = 3
C = np.fromfunction(lambda i,j: 1 if i < k else 0, (3,3))

但是,这段代码抛出了一个错误

"具有多个元素的数组的真值是不明确的。 使用 a.any() 或 a.all()" 我不太明白为什么。

【问题讨论】:

  • 创建一个零数组c=np.zeros((3,3)),然后c[:k,:]=1?
  • 这可行,但我对这个错误的性质很感兴趣。
  • 嗯?当然l = lambda i,j: 1 if i &lt; k else 0C = np.fromfunction(np.vectorize(l), (5,3))
  • np.fromfunction 只是创建一个网格,并通过一次调用将整个内容传递给您的函数。看看它的代码。

标签: python python-3.x numpy matrix vectorization


【解决方案1】:

fromfunction 的代码是:

dtype = kwargs.pop('dtype', float)
args = indices(shape, dtype=dtype)
return function(*args, **kwargs)

你看到它只调用了一次function - 整个数组indices。它不是迭代的。

In [672]: idx = np.indices((3,3))                                                    
In [673]: idx                                                                        
Out[673]: 
array([[[0, 0, 0],
        [1, 1, 1],
        [2, 2, 2]],

       [[0, 1, 2],
        [0, 1, 2],
        [0, 1, 2]]])

您的 lambda 需要标量 i,j 值,而不是 3d 数组

 lambda i,j: 1 if i < k else 0

idx&lt;3 是一个 3d 布尔数组。在 if 上下文中使用时会出现错误。

如果您想将标量函数应用于一组数组,np.vectorizenp.frompyfunc 会更好:

In [677]: np.vectorize(lambda i,j: 1 if i < 2 else 0)(idx[0],idx[1])                 
Out[677]: 
array([[1, 1, 1],
       [1, 1, 1],
       [0, 0, 0]])

但是它并不比更直接的迭代方法快,而且比对整个数组进行操作的函数慢。

许多全数组方法之一:

In [680]: np.where(np.arange(3)[:,None]<2, np.ones((3,3),int), np.zeros((3,3),int))  
Out[680]: 
array([[1, 1, 1],
       [1, 1, 1],
       [0, 0, 0]])

【讨论】:

    【解决方案2】:

    根据@MarkSetchell 的建议,您需要vectorize 您的函数:

    k = 3
    f = lambda i,j: 1 if i < k else 0
    
    C = np.fromfunction(np.vectorize(f), (3,3))
    

    你会得到:

    C
    array([[1, 1, 1],
           [1, 1, 1],
           [1, 1, 1]])
    

    【讨论】:

    • 他还建议用 5 行进行整形,以便您查看和检查结果!
    • @MarkSetchell 他确实很聪明。
    【解决方案3】:

    问题在于np.fromfunction 不会遍历所有元素,它只返回每个维度的索引。您可以使用np.where() 根据这些索引应用条件,根据条件从两个备选方案中进行选择:

    import numpy as np
    
    k = 3
    np.fromfunction(lambda i, j: np.where(i < k, 1, 0), (5,3))
    

    给出:

    array([[1, 1, 1],
           [1, 1, 1],
           [1, 1, 1],
           [0, 0, 0],
           [0, 0, 0]])
    

    这避免了命名 lambda 而不会使事情变得过于笨拙。在我的笔记本电脑上,这种方法比 np.vectorize() 快了大约 20 倍。

    【讨论】:

      猜你喜欢
      • 2020-02-14
      • 2019-11-09
      • 1970-01-01
      • 2011-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多