2017-07-28 19 views
6

当参数是列表或元组时,np.c_的输出有所不同。考虑以下三个行的输出带有列表和元组参数的np.c_的行为

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

随着list参数,np.c_返回一个列阵列,如所预期。当参数是一个元组(第二行)时,它返回一个2D行。在元组(第三行)之后,为第一个调用返回一个列数组后的逗号。

有人可以解释这种行为的基本原理吗?

+0

看看代码。文件中的这个和其他类/函数('indexing_tricks'?)是一个方便但有趣的编码。 – hpaulj

回答

4

有2共同使用情况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_可以传递1D数组或喜欢2D数组。 但是,这引发了一个问题,np.c_应该如何识别输入是单个2D数组(如[[1,2],[3,4]]还是1D数组类喜欢的序列(例如[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)作为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时的不同处理方式。

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 
    ....