将功能应用于3D numpy数组的每个2D切片的有效方法 [英] Efficient way to apply function to each 2D slice of 3D numpy array
问题描述
我想将一个采用2D数组(并返回相同形状之一)的函数应用于3D数组的每个2D切片.什么是有效的方法? numpy.fromiter
返回一维数组,并且numpy.fromfunction
需要分别应用于每个坐标.
I want to apply a function that takes a 2D array (and returns one of the same shape) to each 2D slice of a 3D array. What's an efficient way of doing this? numpy.fromiter
returns a 1D array and numpy.fromfunction
needs to be applied to each coordinate individually.
我现在正在做
foo = np.array([func(arg, bar2D) for bar2D in bar3D])
这给了我我想要的,但是列表理解很慢.同样,func
是具有特定边界条件的一维导数. numpy.gradient
似乎只对数组维数为N的N-D个导数,但是也许还有另一个例程可以为我做全部事情?
This gives me what I want, but the list comprehension is very slow. Also, func
is a 1D derivative with particular boundary conditions. numpy.gradient
only seems to do N-D derivatives with N the dimension of the array, but maybe there is another routine that will do the whole thing for me?
编辑:列表理解有效,但我正在寻找一种更快的方法. bar3D
可以很大,最大为(500,500,1000)
.我发现的将函数应用于数组的所有numpy
例程似乎都假设函数或数组都是一维的.
Edit: The list comprehension works, but I'm looking for a faster way of doing it. bar3D
can be large, up to (500,500,1000)
. All the numpy
routines I've found for applying functions to arrays seem to assume either the function or the array are 1D.
推荐答案
我不知道将函数应用于N-D数组切片的任何通用方法.但是有两种方法可以解决它.
I don't know of any generic way to apply functions to N-D slices of arrays. But there are two ways to get around it.
如果要在每个2D切片的每一行或每一列上应用一维导数,则等同于将导数应用于每个1D切片,您可以使用np.apply_along_axis:
If what you want to do is apply a 1D derivative on each row or column of each 2D-slice, this is equivalent to applying the derivative to each 1D slice, and you can use np.apply_along_axis:
values = np.arange(4)*np.arange(3)[:, None]+np.arange(2)[:, None, None]*2
>>> array([[[0, 0, 0, 0],
[0, 1, 2, 3],
[0, 2, 4, 6]],
[[2, 2, 2, 2],
[2, 3, 4, 5],
[2, 4, 6, 8]]])
np.apply_along_axis(np.gradient, 2, values)
>>> array([[[ 0., 0., 0., 0.],
[ 1., 1., 1., 1.],
[ 2., 2., 2., 2.]],
[[ 0., 0., 0., 0.],
[ 1., 1., 1., 1.],
[ 2., 2., 2., 2.]]])
这可以区分每个2D切片的行.要区分每列,请np.apply_along_axis(np.gradient, 2, values)
This differentiates the rows of each 2D slice. To differantiate each column do np.apply_along_axis(np.gradient, 2, values)
如果要执行需要二维的操作,通常可以通过广播和轴参数来获得它.例如,如果您要为每个切片V
V[i, j] = sqrt((V[i,j]-V[i, j-1])^2+V[i, j]-V[i-1, j])^2
,则可以执行以下操作:
If you want to do something that requires two dimensions, you can usually get it through broadcasting and axis parameters. If for instance you want V[i, j] = sqrt((V[i,j]-V[i, j-1])^2+V[i, j]-V[i-1, j])^2
for each slice V
you can do:
xdiffs = np.zeros_like(values)
xdiffs[:, 1:, :]= np.diff(values, axis=1)
ydiffs = np.zeros_like(values)
ydiffs[:, :, 1:] = np.diff(values, axis=2)
diffnorms = np.linalg.norm(xdiffs, ydiffs)
>>> array(
[[[ 0. , 0. , 0. , 0. ],
[ 0. , 1.41421356, 2.23606798, 3.16227766],
[ 0. , 2.23606798, 2.82842712, 3.60555128]],
[[ 0. , 0. , 0. , 0. ],
[ 0. , 1.41421356, 2.23606798, 3.16227766],
[ 0. , 2.23606798, 2.82842712, 3.60555128]]])
正确设置尺寸有点麻烦,但通常是最有效的解决方案.
It's a bit cumbersome to get the dimensions right, but it will usually be the most efficient solution.
此示例在边界处使用零,如果您需要其他内容,则需要将normdiff[:, :, 0]
和normdiff[:, 0, :]
设置为正确的边界值.
This examples uses zeros at the boundries, if you need something else, you need to set normdiff[:, :, 0]
and normdiff[:, 0, :]
to the correct boundry values.
这篇关于将功能应用于3D numpy数组的每个2D切片的有效方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!