简单的Numpy二维矩阵和网格- ValueError:具有多个元素的数组的真值是不明确的。

时间:2022-09-05 16:07:42

I'm new to Python, and this task is probably simple, but I'm just not getting it. I'm trying to model light transmission through a 2-D aperture using a grid: if light is transmitted, the grid-element is 1; if not, then 0.

我是Python的新手,这个任务可能很简单,但是我没有得到它。我试着用栅格来模拟光波通过二维光圈:如果光传输,网格单元为1;如果不是,那么0。

I'm having trouble when iterating through the 2-D matrix. I think there is an issue when comparing an element of the numpy array to the scalar value, especially because two conditions must be met. I tried a.any() and a.all(), &, and np.logical_and(), but I can't seem to get them to work.

我在迭代二维矩阵时遇到了麻烦。我认为将numpy数组的元素与标量值进行比较是有问题的,特别是因为必须满足两个条件。我试过了a.any()和a.all(), &和np.logical_and(),但我似乎无法让他们工作。

def make_object(x,y,a,b):
    f = np.zeros((len(x),len(y)))

    if np.abs(x) < (a/2.0):
        if np.abs(y) < (b/2.0):
            f[x][y] = 1.0
    return f


a = 6.0  # Width of slit
b = 6.0  # Height of slit
N = 20.0
x = np.linspace(-10.0,10.0,N)
y = np.linspace(-10.0,10.0,N)
X,Y = np.meshgrid(x,y)

z = make_object(X,Y,a,b)
print z

I get this error message:

我得到这个错误信息:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-13-fef282d4a308> in <module>()
     29 x,y = np.meshgrid(x,y)
     30 
---> 31 z = make_object(x,y,a,b)
     32 
     33 

<ipython-input-13-fef282d4a308> in make_object(x, y, a, b)
      8     f = np.zeros((len(x),len(y)))
      9 
---> 10     if np.abs(x) < (a/2.0):
     11         if np.abs(y) < (b/2.0):
     12             f[x][y] = 1.0

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Any ideas what I'm doing wrong?

你知道我做错了什么吗?

Edit: Code used previously without vectorization

编辑:以前没有向量化的代码。

for i, xi in enumerate(x):
    for j, yj in enumerate(y):
        if np.abs(xi) < a/2:
            if np.abs(yj) < b/2:
                f[i][j] = 1.0

2 个解决方案

#1


1  

The problem is x and y are arrays, not individual elements. Heres what your code evaluates to before it reaches an error:

问题是x和y是数组,而不是单个元素。在它到达错误之前,您的代码会对其进行评估:

if array([True, False, ... ]):

To Python, evaluating whether an entire array is True or False makes no sense. If you want to use if statements, you have to iterate through the array and check if individual elements are less than the cutoff rather than entire arrays.

对Python来说,评估整个数组是真还是假毫无意义。如果要使用If语句,则必须遍历数组并检查单个元素是否小于截止值,而不是整个数组。

for i in range(f.shape[0]):
    for j in range(f.shape[1]):
        if x[i][j] < a/2:
           if y[i][j] < b/2:
                f[i][j] = 1

However, since you are using NumPy, you do not need if statements and can take advantage of vectorization and solve your problem in a single line.

但是,由于您使用的是NumPy,所以您不需要if语句,并且可以利用矢量化并在一行中解决您的问题。

f[ np.logical_and(np.abs(x) < a/2.0,  np.abs(y) < b/2.0) ] = 1

#2


0  

Comparison operators acting on numpy arrays operate on a element-wise basis, i.e.

在numpy阵列上操作的比较运算符以一个元素为基础进行操作,即:

array([0, 0, 0, 3]) > 2 will produce array([False, False, False, True])

数组([0,0,0,3])> 2将产生数组([False, False, False, True])

Rohanp's solution will work, but I'd also suggest the useful numpy function where, which would be used in one of two ways.

Rohanp的解决方案是可行的,但我还建议使用一个有用的numpy函数,它将以两种方式之一使用。

Option 1: insert values to create z directly

选项1:插入值直接创建z。

truevals = numpy.ones_like(X) #(or = numpy.zeros_like(X) + desired_value)
falsevals = numpy.zeros_like(X)
z = numpy.where((np.abs(X) < 6.0) & (np.abs(Y) < 6.0), truevals, falsevals)  

note the use of & rather than "and"!

注意使用&而不是“和”!

Option 2: return indices where conditions are true

选项2:返回条件为真的返回指数。

This would be more useful if you don't want to simply insert one value or another, but perhaps do some more complex analysis only on those positions which evaluate as true, and ignore the rest

如果您不想简单地插入一个值或另一个值,那么这将更有用,但是可能只对那些值为true的位置做一些更复杂的分析,而忽略其余的。

indices = numpy.where((np.abs(X) < 6.0) & (np.abs(Y) < 6.0))
z = numpy.zeros_like(X)
for i, j in zip(*indices):
    z[i][j] = 5*(i+j) # for example

#1


1  

The problem is x and y are arrays, not individual elements. Heres what your code evaluates to before it reaches an error:

问题是x和y是数组,而不是单个元素。在它到达错误之前,您的代码会对其进行评估:

if array([True, False, ... ]):

To Python, evaluating whether an entire array is True or False makes no sense. If you want to use if statements, you have to iterate through the array and check if individual elements are less than the cutoff rather than entire arrays.

对Python来说,评估整个数组是真还是假毫无意义。如果要使用If语句,则必须遍历数组并检查单个元素是否小于截止值,而不是整个数组。

for i in range(f.shape[0]):
    for j in range(f.shape[1]):
        if x[i][j] < a/2:
           if y[i][j] < b/2:
                f[i][j] = 1

However, since you are using NumPy, you do not need if statements and can take advantage of vectorization and solve your problem in a single line.

但是,由于您使用的是NumPy,所以您不需要if语句,并且可以利用矢量化并在一行中解决您的问题。

f[ np.logical_and(np.abs(x) < a/2.0,  np.abs(y) < b/2.0) ] = 1

#2


0  

Comparison operators acting on numpy arrays operate on a element-wise basis, i.e.

在numpy阵列上操作的比较运算符以一个元素为基础进行操作,即:

array([0, 0, 0, 3]) > 2 will produce array([False, False, False, True])

数组([0,0,0,3])> 2将产生数组([False, False, False, True])

Rohanp's solution will work, but I'd also suggest the useful numpy function where, which would be used in one of two ways.

Rohanp的解决方案是可行的,但我还建议使用一个有用的numpy函数,它将以两种方式之一使用。

Option 1: insert values to create z directly

选项1:插入值直接创建z。

truevals = numpy.ones_like(X) #(or = numpy.zeros_like(X) + desired_value)
falsevals = numpy.zeros_like(X)
z = numpy.where((np.abs(X) < 6.0) & (np.abs(Y) < 6.0), truevals, falsevals)  

note the use of & rather than "and"!

注意使用&而不是“和”!

Option 2: return indices where conditions are true

选项2:返回条件为真的返回指数。

This would be more useful if you don't want to simply insert one value or another, but perhaps do some more complex analysis only on those positions which evaluate as true, and ignore the rest

如果您不想简单地插入一个值或另一个值,那么这将更有用,但是可能只对那些值为true的位置做一些更复杂的分析,而忽略其余的。

indices = numpy.where((np.abs(X) < 6.0) & (np.abs(Y) < 6.0))
z = numpy.zeros_like(X)
for i, j in zip(*indices):
    z[i][j] = 5*(i+j) # for example