Python,numpy;如何最好地处理可能的0d数组

时间:2016-02-25 02:24:49

标签: python arrays numpy

Python numpy ndarrays让我失望了!我可以回到Matlab吗?

假设我有一个期望ndarray矢量输入的函数。我使用numpy.asarray函数强制输入到我想要的形式,方便的是没有重复已经是ndarrays的东西。但是,如果标量被传入,它有时会变成0d数组而不是1d数组,具体取决于它是如何传入的.0d数组会导致问题,因为我可以索引它。

首先,为什么我不能?说x = np.array(1)。然后是x.size == 1,所以它应该有第0个元素。为什么我不能x[0]x[-1]。我知道它希望喜欢一个python int,但它应该在int上进行改进,而不是故意给出相同的限制。

其次,如果numpy asarray函数有一些可选输入来强制输出始终至少为1d数组,那将是非常棒的。然后我可以做x = np.asarray(x, force_at_least_1d=True)

之类的事情

然而,我能想出的最佳选择是检查ndim属性,如果它是0,则将其扩展为1.这对我来说感觉不对。我还缺少一些其他的选择吗?

import numpy as np

def func(x, extra_check=True):
    r"""Meaningless Example Function for stackoverflow."""
    # force input to be ndarrays
    x = np.asarray(x)

    if x.size == 0:
        print('Don''t do anything.')

    # Extra test to deal with garbage 0D arrays so that they can be indexed by keep.
    # This test is really bothering me.  Is there a better way to make it unnecessary?
    if extra_check and (x.ndim == 0):
        x = x[np.newaxis]

    if x[0] > 0 and x[-1] > 5:
        print('Do something cool.')
    else:
        print('Do something less cool.')

if __name__ == '__main__':
    # nominally intended use
    x1 = np.array([1, 2, 10])
    y1 = func(x1) # prints "Do something cool."

    # single item use
    x2 = x1[x1 == 2]
    y2 = func(x2) # prints "Do something less cool."

    # scalar single item use that works with extra check
    x3 = x1[1]
    y3 = func(x3) # prints "Do something less cool."

    # scalar single item that will fail without extra check
    x4 = x1[1]
    y4 = func(x4, extra_check=False) # raises IndexError

所以我的主要问题是,是否有比我更好的方式。如果没有,其他人是否同意应该有?我对Python比较陌生,所以我从来没有尝试过为源代码贡献任何东西,但我想我可以寻找另一个问题来解释这个过程。

如果重要的话,我在python v3.5.1和numpy 1.9.3上。谢谢!

2 个答案:

答案 0 :(得分:13)

  

其次,如果numpy asarray函数有一些可选输入来强制输出始终至少为1d数组,那将是非常棒的。然后我可以做类似x = np.asarray(x,force_at_least_1d = True)的事情。

np.asarray没有,但np.array确实 - ndmin - 还有专门的np.atleast_1d功能(也是2和3):

>>> np.array(0, ndmin=1)
array([0])
>>> np.atleast_1d(np.array(0))
array([0])

答案 1 :(得分:2)

任何数组都可以使用带有x.ndim元素的元组进行索引

2D:

In [238]: x=np.array([[1]])
In [239]: x.ndim
Out[239]: 2
In [240]: x[(0,0)]   # same as x[0,0]
Out[240]: 1

1D:

In [241]: x=np.array([1])    
In [242]: x[(0,)]     # (0,) to distinguish from (0)==0
Out[242]: 1

0D:

In [243]: x=np.array(1)    
In [244]: x[()]      # empty tuple
Out[244]: 1

索引元素实际上不会返回标量

In [250]: x=np.array([[1]])

In [251]: type(x[0,0])
Out[251]: numpy.int32

In [252]: x[0,0][()]
Out[252]: array(1)

它返回一个dtype对象,它接受0d索引。

你提到MATLAB。 - 一切都是2d(或更高);将0d设置为下限是不是更合乎逻辑? :)

另一个答案提到ndmin参数,以及atleast_1d(还有2d和3d)。查看atleast_1d的文档和代码,了解它如何重塑各种案例。 e.g。

 if len(ary.shape) == 0 :
     result = ary.reshape(1)