我希望从一个函数创建一个矩阵,这样,如果行索引小于给定的阈值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()”,我不太明白为什么。
发布于 2019-04-26 09:19:28
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
值,而不是三维数组。
lambda i,j: 1 if i < k else 0
idx<3
是一个三维布尔数组。当在if
上下文中使用它时,会出现错误。
如果要将标量函数应用于一组数组,则np.vectorize
或np.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]])
发布于 2019-04-26 02:37:27
正如@MarkSetchell所建议的,您需要矢量化您的函数:
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]])
发布于 2019-04-26 06:05:09
问题是,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倍。
https://stackoverflow.com/questions/55865031
复制