np.c_与list和tuple参数的行为

时间:2017-07-28 14:43:41

标签: python numpy

np.c_的输出在其参数是列表或元组时有所不同。考虑以下三行的输出

np.c_[[1,2]]
np.c_[(1,2)]
np.c_[(1,2),]

使用list参数,np.c_按预期返回列数组。当参数是元组(第二行)时,它返回一个2D行。在元组(第三行)之后添加逗号将返回与第一次调用相同的列数组。

有人可以解释这种行为背后的理由吗?

2 个答案:

答案 0 :(得分:5)

np.c_有两个常见用例:

  • np.c_可以接受一系列1D数组:

    In [98]: np.c_[[1,2],[3,4]]
    Out[98]: 
    array([[1, 3],
           [2, 4]])
    
  • 或,np.c_可以接受一系列2D数组:

    In [96]: np.c_[[[1,2],[3,4]], [[5,6],[7,8]]]
    Out[96]: 
    array([[1, 2, 5, 6],
           [3, 4, 7, 8]])
    

所以np.c_可以传递一维数组或2D数组。 但这提出了一个问题:如果输入是单个2D数组(例如[[1,2],[3,4]])或一维数组序列,np.c_应该如何识别({1}}例如[1,2],[3,4])?

开发人员做出了一个设计决策:如果np.c_传递了一个元组,那么该参数将被视为一系列独立的数组。如果它传递了非元组(例如列表),那么该对象将被视为单个数组。

因此,np.c_[[1,2], [3,4]](相当于np.c_[([1,2], [3,4])])会将([1,2], [3,4])视为两个独立的1D数组。

In [99]: np.c_[[1,2], [3,4]]
Out[99]: 
array([[1, 3],
       [2, 4]])

相比之下,np.c_[[[1,2], [3,4]]]会将[[1,2], [3,4]]视为单个2D数组。

In [100]: np.c_[[[1,2], [3,4]]]
Out[100]: 
array([[1, 2],
       [3, 4]])

因此,对于您发布的示例:

np.c_[[1,2]][1,2]视为单个1D数组,因此它将[1,2]转换为2D数组的列:

In [101]: np.c_[[1,2]]
Out[101]: 
array([[1],
       [2]])

np.c_[(1,2)](1,2)视为两个独立的数组,因此它将每个值放入其自己的列中:

In [102]: np.c_[(1,2)]
Out[102]: array([[1, 2]])

np.c_[(1,2),]将元组(1,2),(相当于((1,2),))视为一个类似数组的序列,以便将类似数组视为列:

In [103]: np.c_[(1,2),]
Out[103]: 
array([[1],
       [2]])

PS。也许比大多数软件包更多,NumPy的历史记录为treating lists and tuples differently。该链接讨论了传递给np.array时列表和元组如何被区别对待。

答案 1 :(得分:2)

处理参数的第一个级别来自Python解释器,它将[...]转换为对__getitem__的调用:

In [442]: class Foo():
     ...:     def __getitem__(self,args):
     ...:         print(args)
     ...:        
In [443]: Foo()['str']
str
In [444]: Foo()[[1,2]]
[1, 2]
In [445]: Foo()[[1,2],]
([1, 2],)
In [446]: Foo()[(1,2)]
(1, 2)
In [447]: Foo()[(1,2),]
((1, 2),)

np.c_np.lib.index_tricks.AxisConcatenator的一个实例。这是__getitem__

    # handle matrix builder syntax
    if isinstance(key, str):
        ....
        mymat = matrixlib.bmat(...)
        return mymat

    if not isinstance(key, tuple):
        key = (key,)

     ....
    for k, item in enumerate(key):
        ....

除了np.bmat兼容字符串之外,它将所有输入转换为元组,然后迭代元素。

包含[1,2]的任何变体都与([1,2],)相同,即单个元素元组。 (1,2)是两个将被连接起来的元素。 ([1,2],[3,4])也是如此。

请注意,numpy索引还可以区分列表和元组(尽管存在一些不一致)。

In [455]: x=np.arange(24).reshape(2,3,4)
In [456]: x[0,1]               # tuple - index for each dim
Out[456]: array([4, 5, 6, 7])
In [457]: x[(0,1)]             # same tuple
Out[457]: array([4, 5, 6, 7])
In [458]: x[[0,1]]             # list - index for one dim
Out[458]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])
In [459]: x[([0,1],)]          # same
     ....