numpy meshgrid 操作问题 [英] numpy meshgrid operations problems

查看:49
本文介绍了numpy meshgrid 操作问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Y, X = np.mgrid[-3:-3:10j, -3:3:10j]

我注意到,当在上面的网格上应用某些操作时,我收到一个错误,因为这些操作可能与 numpy 不兼容.有时可能有一个 numpy 函数替代 sin、cos,但不是所有函数,如 scipy.integrate 中的 quad 函数.

I've noticed that when applying certain operations on meshgrids like the one above I get an error because the operations may not be compatible with numpy. Sometimes there might be a numpy function alternative for sin, cos but not for all function like the quad function in scipy.integrate.

我该如何解决这个问题?我需要在整个网格上应用操作.

How do I get around this problem? I need to apply operations on the entire meshgrids.

推荐答案

您的问题(带有后续评论)至少可以通过两种不同的方式提出:

Your question (with the follow-on comment) can be taken at least two different ways:

  1. 您有一个具有多个参数的函数,并且您希望能够以一种在语法上类似于 numpy 原生支持的广播调用的方式来调用该函数.性能不是问题,只是函数的调用语法.

  1. You have a function of multiple arguments, and you would like to be able to call that function in a manner that is syntactically similar to the broadcasted calls supported natively by numpy. Performance is not the issue, just the calling syntax of the function.

您有一个包含多个参数的函数,该函数将在一系列 numpy 数组上进行评估,但该函数的实现方式无法利用 numpy 数组的连续内存布局.性能是问题;您会很乐意循环遍历 numpy 数组并以无聊的、普通的旧 for 循环样式调用您的函数,但这样做太慢了.

You have a function of multiple arguments that is to be evaluated on a sequence of numpy arrays, but the function is not implemented in such a manner that it can exploit the contiguous memory layout of numpy arrays. Performance is the issue; you would be happy to loop over the numpy arrays and call your function in a boring, plain old for-loop style, except that doing so is too slow.

对于第 1 项,numpy 提供了一个名为 vectorize 的便利函数,它接受一个常规可调用对象并返回一个可调用对象,该可调用对象可以使用 numpy 数组作为参数进行调用,并且将遵守 numpy 的广播规则.

For item 1. there is a convenience function provided by numpy called vectorize which takes a regular callable and returns a callable that can be called with numpy arrays as the arguments and will obey numpy's broadcasting rules.

考虑这个人为的例子:

def my_func(x, y):
    return x + 2*y

现在假设我需要在二维网格中的任何地方评估这个函数.这是普通的老式无聊方式:

Now suppose I need to evaluate this function everywhere in a 2-D grid. Here is the plain old boring way:

Y, X  =  np.mgrid[0:10:1, 0:10:1]
Z = np.zeros_like(Y)

for i in range(Y.shape[0]):
    for j in range(Y.shape[1]):
        Z[i,j] = my_func(X[i,j], Y[i,j])

如果我们有几个不同的函数,比如 my_func,那么将这个过程概括为一个函数可能会很好,该函数将给定的函数映射"到二维数组上.

If we had a few different functions like my_func, it might be nice to generalize this process into a function that "mapped" a given function over the 2-D arrays.

import itertools
def array_map(some_func, *arg_arrays):
    output = np.zeros_like(arg_arrays[0])
    coordinates = itertools.imap(range, output.shape)
    for coord in itertools.product(coordinates):
        args = [arg_array[coord] for arg_array in arg_arrays]
        output[coord] = some_func(*args)
    return output

现在我们可以看到 array_map(my_func, X, Y) 就像嵌套的 for 循环一样:

Now we can see that array_map(my_func, X, Y) acts just like the nested for-loop:

In [451]: array_map(my_func, X, Y)
Out[451]: 
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [ 2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
       [ 4,  5,  6,  7,  8,  9, 10, 11, 12, 13],
       [ 6,  7,  8,  9, 10, 11, 12, 13, 14, 15],
       [ 8,  9, 10, 11, 12, 13, 14, 15, 16, 17],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [12, 13, 14, 15, 16, 17, 18, 19, 20, 21],
       [14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
       [16, 17, 18, 19, 20, 21, 22, 23, 24, 25],
       [18, 19, 20, 21, 22, 23, 24, 25, 26, 27]])

现在,如果我们可以调用 array_map(my_func) 并省去额外的数组参数不是很好吗?取而代之的是取回一个新函数,该函数正在等待执行所需的 for 循环.

Now, wouldn't it be nice if we could call array_map(my_func) and leave off the extra array arguments? Instead just getting back a new function that was just waiting to do the required for-loops.

我们可以用 functools.partial 做到这一点——这样我们就可以写一个像这样方便的小向量化器:

We can do this with functools.partial -- so we can write a handy little vectorizer like this:

import functools
def vectorizer(regular_function):
    awesome_function = functools.partial(array_map, regular_function)
    return awesome_function

并进行测试:

In [453]: my_awesome_func = vectorizer(my_func)

In [454]: my_awesome_func(X, Y)
Out[454]: 
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [ 2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
       [ 4,  5,  6,  7,  8,  9, 10, 11, 12, 13],
       [ 6,  7,  8,  9, 10, 11, 12, 13, 14, 15],
       [ 8,  9, 10, 11, 12, 13, 14, 15, 16, 17],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [12, 13, 14, 15, 16, 17, 18, 19, 20, 21],
       [14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
       [16, 17, 18, 19, 20, 21, 22, 23, 24, 25],
       [18, 19, 20, 21, 22, 23, 24, 25, 26, 27]])

现在 my_awesome_func 的行为就像您可以直接在 ndarrays 之上调用它一样!

Now my_awesome_func behaves as if you are able to call it directly on top of ndarrays!

我在制作这个名为 vectorizer 的玩具版本时忽略了许多额外的小性能细节、边界检查等……但幸运的是,在 numpy 中有 vectorize这已经做到了!

I've overlooked many extra little performance details, bounds checking, etc., while making this toy version called vectorizer ... but luckily in numpy there is vectorize which already does just this!

In [455]: my_vectorize_func = np.vectorize(my_func)

In [456]: my_vectorize_func(X, Y)
Out[456]: 
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [ 2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
       [ 4,  5,  6,  7,  8,  9, 10, 11, 12, 13],
       [ 6,  7,  8,  9, 10, 11, 12, 13, 14, 15],
       [ 8,  9, 10, 11, 12, 13, 14, 15, 16, 17],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [12, 13, 14, 15, 16, 17, 18, 19, 20, 21],
       [14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
       [16, 17, 18, 19, 20, 21, 22, 23, 24, 25],
       [18, 19, 20, 21, 22, 23, 24, 25, 26, 27]])

再次强调,正如我之前对 OP 的评论和 vectorize 文档中所强调的那样——这 不是速度优化.实际上,在某些情况下,额外的函数调用开销会比直接编写 for 循环慢.但是,对于速度不成问题的情况,此方法确实允许您使自定义函数遵循与 numpy 相同的调用约定——这可以提高库接口的统一性并使代码更加一致和更具可读性.

Once again, as stressed in my earlier comments to the OP and in the documentation for vectorize -- this is not a speed optimization. In fact, the extra function calling overhead will be slower in some cases than just writing a for-loop directly. But, for cases when speed is not a problem, this method does allow you to make your custom functions adhere to the same calling conventions as numpy -- which can improve the uniformity of your library's interface and make the code more consistent and more readable.

关于第 2 项已经写了很多其他的东西.如果您的问题是您需要优化函数以利用连续的内存块并绕过重复的动态类型检查(numpy 数组添加的主要功能)到 Python 列表),那么这里有一些您可能会觉得有用的链接:

A whole lot of other stuff has already been written about item 2. If your problem is that you need to optimize your functions to leverage contiguous blocks of memory and by-passing repeated dynamic type checking (the main features that numpy arrays add to Python lists) then here are a few links you may find helpful:

  1. <http://pandas.pydata.org/pandas-docs/stable/enhancingperf.html >
  2. <http://csl.name/C-functions-from-Python/ >
  3. <https://jakevdp.github.io/blog/2014/05/09/why-python-is-slow >

这篇关于numpy meshgrid 操作问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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