简体   繁体   English

从函数创建矩阵

[英]Create a matrix from a function

I want to create a matrix from a function, such that the (3,3) matrix C has values equal to 1 if the row index is smaller than a given threshold k.我想从一个函数创建一个矩阵,如果行索引小于给定的阈值 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))

However, this piece of code throws an error但是,这段代码抛出错误

"The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()" and I do not really understand why. “具有多个元素的数组的真值不明确。使用 a.any() 或 a.all()”,我真的不明白为什么。

The code for fromfunction is: fromfunction的代码是:

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

You see it calls function just once - with the whole array of indices .您会看到它只调用一次function - 使用整个indices数组。 It is not iterative.它不是迭代的。

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]]])

Your lambda expects scalar i,j values, not a 3d array您的 lambda 期望标量i,j值,而不是 3d 数组

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

idx<3 is a 3d boolean array. idx<3是一个 3d 布尔数组。 The error arises when that is use in an if context.if上下文中使用时会出现错误。

np.vectorize or np.frompyfunc is better if you want to apply a scalar function to a set of arrays:如果要将标量函数应用于一组数组,则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]])

However it isn't faster than more direct iterative approaches, and way slower than functions that operation on whole arrays.然而,它并不比更直接的迭代方法快,而且比在整个数组上运行的函数慢得多。

One of many whole-array approaches:许多全阵列方法之一:

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]])

As suggested by @MarkSetchell you need to vectorize your function:正如@MarkSetchell 所建议的,您需要对函数进行矢量化

k = 3
f = lambda i,j: 1 if i < k else 0

C = np.fromfunction(np.vectorize(f), (3,3))

and you get:你得到:

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

The problem is that np.fromfunction does not iterate over all elements, it only returns the indices in each dimension.问题是np.fromfunction不会遍历所有元素,它只返回每个维度中的索引。 You can use np.where() to apply a condition based on those indices, choosing from two alternatives depending on the condition:您可以使用np.where()应用基于这些索引的条件,根据条件从两个备选方案中进行选择:

import numpy as np

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

which gives:这使:

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

This avoids naming the lambda without things becoming too unwieldy.这避免了命名 lambda 而不会变得太笨重。 On my laptop, this approach was about 20 times faster than np.vectorize() .在我的笔记本电脑上,这种方法比np.vectorize()快大约 20 倍。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM