Python Numpy 错误:形状不匹配
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23691498/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Numpy error: shape mismatch
提问by seekiu
When I was trying to solve a scientific problem with Python (Numpy), a 'shape mismatch' error came up: "shape mismatch: objects cannot be broadcast to a single shape". I managed to reproduce the same error in a simpler form, as shown below:
当我尝试使用 Python (Numpy) 解决科学问题时,出现了“形状不匹配”错误:“形状不匹配:对象无法广播为单个形状”。我设法以更简单的形式重现了相同的错误,如下所示:
import numpy as np
nx = 3; ny = 5
ff = np.ones([nx,ny,7])
def test(x, y):
z = 0.0
for i in range(7):
z = z + ff[x,y,i]
return z
print test(np.arange(nx),np.arange(ny))
When I tried to call test(x,y)
with x=1,y=np.arange(ny)
, everything works fine. So what's going on here? Why can't the both parameters be numpy arrays?
当我尝试用 打电话test(x,y)
时x=1,y=np.arange(ny)
,一切正常。那么这里发生了什么?为什么这两个参数不能都是 numpy 数组?
UPDATE
更新
I have worked out the problem with some hints from @Saullo Castro. Here's some updated info for you guys who tried to help but feel unclear about my intention:
我已经通过@Saullo Castro 的一些提示解决了这个问题。这里有一些更新的信息,供那些试图提供帮助但不清楚我的意图的人:
Basically I created a mesh grid with dimension nx*ny and another array ff
that stores some value for each node. In the above code, ff
has 7 values for each node and I was trying to sum up the 7 values to get a new nx*ny array.
基本上我创建了一个尺寸为 nx*ny 的网格和另一个ff
为每个节点存储一些值的数组。在上面的代码中,ff
每个节点有 7 个值,我试图总结这 7 个值以获得一个新的 nx*ny 数组。
However, the "shape mismatch" error is not due to the summing process as many of you might have guess now. I have misunderstood the rule of functions taking ndarray objects as input parameters. I tried to pass np.arange(nx), np.arange(ny)
to test()
is not gonna give me what I desired, even if nx==ny
.
然而,“形状不匹配”错误并不是你们许多人现在可能已经猜到的求和过程造成的。我误解了将 ndarray 对象作为输入参数的函数规则。我试图传递np.arange(nx), np.arange(ny)
给test()
不会给我我想要的东西,即使nx==ny
.
Back to my original intention, I solve the problem by creating another function and used np.fromfunction
to created the array:
回到我的初衷,我通过创建另一个函数并用于np.fromfunction
创建数组来解决问题:
def tt(x, y):
return np.fromfunction(lambda a,b: test(a,b), (x, y))
which is not perfect but it works. (In this example there seems to be no need to create a new function, but in my actual code I modified it a bit so it can be used for slice of the grid)
这并不完美,但它有效。(在这个例子中似乎没有必要创建一个新函数,但在我的实际代码中,我稍微修改了它,以便它可以用于网格切片)
Anyway, I do believe there's a much better way compared to my kind of dirty solution. So if you have any idea about that, please share with us :).
无论如何,我相信有比我那种肮脏的解决方案更好的方法。因此,如果您对此有任何想法,请与我们分享:)。
采纳答案by Saullo G. P. Castro
Let's look into an array similar to your ff
array:
让我们看看一个类似于你的ff
数组的数组:
nx = 3; ny = 4
ff = np.arange(nx*ny*5).reshape(nx,ny,5)
#array([[[ 0, 1, 2, 3, 4],
# [ 5, 6, 7, 8, 9],
# [10, 11, 12, 13, 14],
# [15, 16, 17, 18, 19]],
#
# [[20, 21, 22, 23, 24],
# [25, 26, 27, 28, 29],
# [30, 31, 32, 33, 34],
# [35, 36, 37, 38, 39]],
#
# [[40, 41, 42, 43, 44],
# [45, 46, 47, 48, 49],
# [50, 51, 52, 53, 54],
# [55, 56, 57, 58, 59]]])
When you index using arrays of indices a, b, c
like in ff[a, b, c]
, a, b, c
must have the same shape, and numpy
will build a new array based on the indices. For example:
当您使用a, b, c
in 等索引数组进行索引时ff[a, b, c]
,a, b, c
必须具有相同的形状,并将numpy
根据索引构建一个新数组。例如:
ff[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 2, 3], [0, 0, 0, 1, 1, 1]]
#array([ 0, 5, 20, 26, 51, 56])
This is called fancy indexing, which is like building an array with:
这称为花式索引,就像构建一个数组:
np.array([ff[0, 0, 0], ff[0, 1, 0], ff[1, 0, 0], ..., ff[2, 3, 1]])
In your case the f[x, y, i]
will produce a shape mismatch error since a, b, c
do not have the same shape.
在您的情况下,f[x, y, i]
由于形状不同,将产生形状不匹配错误a, b, c
。
回答by Akavall
Let's reproduce your problem in 2D case, so it is easier to see:
让我们在 2D 情况下重现您的问题,这样更容易看到:
import numpy as np
a = np.arange(15).reshape(3,5)
x = np.arange(3)
y = np.arange(5)
Demo:
演示:
>>> a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
>>> a[x, y] # <- This is the error that you are getting
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: shape mismatch: objects cannot be broadcast to a single shape
# You are getting the error because x and y are different lengths,
# If x and y were the same lengths, the code would work:
>>> a[x, x]
array([ 0, 6, 12])
# mixing arrays and scalars is not a problem
>>> a[x, 2]
array([ 2, 7, 12])
回答by chapelo
It is not clear in your question what you are trying to do or what result are you expecting. It seems, though, that you are trying to calculate a total with your variable z
.
在您的问题中不清楚您正在尝试做什么或您期望什么结果。但是,您似乎正在尝试使用变量 计算总数z
。
Check if the sum
method produces the result that you need:
检查该sum
方法是否产生您需要的结果:
import numpy as np
nx = 3; ny = 5
ff = ff = np.array(np.arange(nx*ny*7)).reshape(nx,ny,7)
print ff.sum() # 5460
print ff.sum(axis=0) # array([[105, 108, 111, 114, 117, 120, 123],
# [126, 129, 132, 135, 138, 141, 144],
# [147, 150, 153, 156, 159, 162, 165],
# [168, 171, 174, 177, 180, 183, 186],
# [189, 192, 195, 198, 201, 204, 207]]) shape(5,7)
print ff.sum(axis=1) # array([[ 70, 75, 80, 85, 90, 95, 100],
# [245, 250, 255, 260, 265, 270, 275],
# [420, 425, 430, 435, 440, 445, 450]]) shape (3,7)
print ff.sum(axis=2) # array([[ 21, 70, 119, 168, 217],
# [266, 315, 364, 413, 462],
# [511, 560, 609, 658, 707]]) shape (3,5)
回答by hpaulj
Looks like you want to sum ff
over the last dimension, with the 1st 2 dimensions covering their whole range. :
is used to denote the whole range of a dimension:
看起来你想对ff
最后一个维度求和,第一个 2 维度覆盖它们的整个范围。 :
用于表示维度的整个范围:
def test():
z = 0.0
for i in range(7):
z = z + ff[:,:,i]
return z
print test()
But you can get the same result without looping, by using the sum
method.
但是通过使用该sum
方法,您无需循环即可获得相同的结果。
print ff.sum(axis=-1)
:
is shorthand for 0:n
:
是简写 0:n
ff[0:nx, 0:ny, 0]==ff[:,:,0]
It is possible to index a block of ff
with ranges, but you have to be much more careful about the shapes of the indexing arrays. For a beginner it is better to focus on getting slicing
and broadcasting
correct.
可以ff
用范围索引一个块,但你必须更加小心索引数组的形状。对于初学者来说,最好专注于获得slicing
和broadcasting
纠正。
edit -
编辑 -
You can index an array like ff
with arrays generated by meshgrid
:
您可以像ff
使用以下方式生成的数组一样索引数组meshgrid
:
I,J = meshgrid(np.arange(nx),np.arange(ny),indexing='ij',sparse=False)
I.shape # (nx,ny)
ff[I,J,:]
also works with
也适用于
I,J = meshgrid(np.arange(nx),np.arange(ny),indexing='ij',sparse=True)
I.shape # (nx,1)
J.shape # (1, ny)
ogrid
and mgrid
are alternatives to meshgrid
.
ogrid
并且mgrid
是 的替代品meshgrid
。