如何以优雅有效的方式在numpy数组上映射python可调用对象? [英] How can I map python callable over numpy array in both elegant and efficient way?

查看:101
本文介绍了如何以优雅有效的方式在numpy数组上映射python可调用对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在数组为空的情况下,规范方法(使用np.vectorize())不起作用-它以IndexError: index 0 is out of bounds for axis 0 with size 0结尾:

The canonical approach (use of np.vectorize()) is not working in case of empty array - it ends with IndexError: index 0 is out of bounds for axis 0 with size 0:

>>> def f(x):
...     return x + 1
...
>>> F = np.vectorize(f)
>>> F(np.array([]))
[Traceback removed]
IndexError: index 0 is out of bounds for axis 0 with size 0

此刻我使用

>>> np.array([f(x) for x in X])

但是我正在寻找更优雅的解决方案(高效).在Python 2中,我可能会选择

but I am looking for more elegant solution (and efficient). In Python 2 I may go with

>>> np.array(map(f, X))

但是在Python 3中失败.

but it fails in Python 3.

对NumPy数组中每个单元的函数进行有效评估,因为:

  • vectorise失败,
  • OP请求的解决方案有效:A(i, j) := f(A(i, j)).
  • vectorise fails,
  • the OP requested solution working in place: A(i, j) := f(A(i, j)).

推荐答案

np.vectorize应该与需要标量的f一起使用.但是,输入为空确实存在问题:

np.vectorize should work with an f that expects a scalar. But, it does have a problem with an empty input:

In [364]: def f(x):
     ...:     return 2*x
     ...: 
In [365]: fv = np.vectorize(f)
In [366]: fv(np.array([1,2,3]))
Out[366]: array([2, 4, 6])
In [367]: fv(np.array([]))
....
ValueError: cannot call `vectorize` on size 0 inputs unless `otypes` is set

我的错误与您的错误不同,但这也许是版本问题.不带otypesvectorize进行测试计算以确定返回类型.如果输入为空,则会出现问题.解决方法是指定otypes.

My error is different than yours, but maybe that's a version issue. vectorize, without otypes makes a test calculation to determine the return type. If the input is empty, that gives a problem. The fix is to specify the otypes.

In [368]: fv1 = np.vectorize(f, otypes=[int])
In [369]: fv1(np.array([]))
Out[369]: array([], dtype=int32)

vectorize使用np.frompyfunc;主要区别在于frompyfunc返回一个对象数组.两者都有一个很大的优势,那就是他们照顾广播.输入可以是任何形状和尺寸的数组.更好的是,它们可以处理多个输入,并相互广播.但是vectorize警告它仍然是迭代的,因此不能保证任何速度上的改进.

vectorize uses np.frompyfunc; the main difference is that frompyfunc returns an object array. Both have the big advantage that they take care of broadcasting. The input can be an array of any shape and dimension. Even better they work with multiple inputs, broadcasting them against each other. But vectorize warns that it is still iterative, so doesn't promise any speed improvements.

阅读链接问题中接受答案的评论.

Read the comments of the accepted answer in the linked question.

但是,如果数组(或列表)始终为1d,则不需要额外的电源.一个普通的Python迭代就和任何东西一样好.可能是map(或py3中的list(map),但是我更喜欢列表理解的清晰性.

But if the array (or list) is always 1d, you don't need that extra power. A plain Python iteration is as good as anything. It could be map (or list(map in py3), but I prefer the clarity of list comprehensions.

ret = [f(x) for x in X]  # works with list or array
np.array(ret)    # if you want an array 


要注意的一件事是各种迭代方法产生的元素的type

对数组进行迭代会产生数组元素或numpy dtypes:

Iteration on an array produces array elements, or numpy dtypes:

In [387]: [type(x) for x in np.arange(3)]
Out[387]: [numpy.int32, numpy.int32, numpy.int32]

列表上的迭代将返回元素,无论它们是什么:

Iteration on a list returns the elements, what ever they are:

In [388]: [type(x) for x in [1,2,3]]
Out[388]: [int, int, int]

使用frompyfunc进行迭代会产生标量"

Iteration with frompyfunc produces 'scalars'

In [389]: ff=np.frompyfunc(type,1,1)
In [390]: ff(np.arange(3))
Out[390]: array([<class 'int'>, <class 'int'>, <class 'int'>], dtype=object)
In [391]: ff([1,2,3])
Out[391]: array([<class 'int'>, <class 'int'>, <class 'int'>], dtype=object)
In [393]: list(map(type,np.arange(3)))
Out[393]: [numpy.int32, numpy.int32, numpy.int32]


vectorize解析otypes的部分是:


The part of vectorize that parses otypes is:

    if isinstance(otypes, str):
        for char in otypes:
            if char not in typecodes['All']:
                raise ValueError("Invalid otype specified: %s" % (char,))
    elif iterable(otypes):
        otypes = ''.join([_nx.dtype(x).char for x in otypes])
    elif otypes is not None:
        raise ValueError("Invalid otype specification")
    self.otypes = otypes

In [423]: np.typecodes['All']
Out[423]: '?bhilqpBHILQPefdgFDGSUVOMm'

这篇关于如何以优雅有效的方式在numpy数组上映射python可调用对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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