将功能应用于3D numpy数组的每个2D切片的有效方法 [英] Efficient way to apply function to each 2D slice of 3D numpy array

查看:128
本文介绍了将功能应用于3D numpy数组的每个2D切片的有效方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将一个采用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆