Numpy reshape 1d to 2d array with 1 column

后端 未结 7 572
一生所求
一生所求 2020-12-08 15:08

In numpy the dimensions of the resulting array vary at run time. There is often confusion between a 1d array and a 2d array with 1 column. In one case I can ite

相关标签:
7条回答
  • 2020-12-08 15:15

    I asked about dtype because your example is puzzling.

    I can make a structured array with 3 elements (1d) and 3 fields:

    In [1]: A = np.ones((3,), dtype='i,i,i')
    In [2]: A
    Out[2]: 
    array([(1, 1, 1), (1, 1, 1), (1, 1, 1)], 
          dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])
    

    I can access one field by name (adding brackets doesn't change things)

    In [3]: A['f0'].shape
    Out[3]: (3,)
    

    but if I access 2 fields, I still get a 1d array

    In [4]: A[['f0','f1']].shape
    Out[4]: (3,)
    In [5]: A[['f0','f1']]
    Out[5]: 
    array([(1, 1), (1, 1), (1, 1)], 
          dtype=[('f0', '<i4'), ('f1', '<i4')])
    

    Actually those extra brackets do matter, if I look at values

    In [22]: A['f0']
    Out[22]: array([1, 1, 1], dtype=int32)
    In [23]: A[['f0']]
    Out[23]: 
    array([(1,), (1,), (1,)], 
          dtype=[('f0', '<i4')])
    

    If the array is a simple 2d one, I still don't get your shapes

    In [24]: A=np.ones((3,3),int)
    In [25]: A[0].shape
    Out[25]: (3,)
    In [26]: A[[0]].shape
    Out[26]: (1, 3)
    In [27]: A[[0,1]].shape
    Out[27]: (2, 3)
    

    But as to question of making sure an array is 2d, regardless of whether the indexing returns 1d or 2, your function is basically ok

    def reshape_to_vect(ar):
        if len(ar.shape) == 1:
          return ar.reshape(ar.shape[0],1)
        return ar
    

    You could test ar.ndim instead of len(ar.shape). But either way it is not costly - that is, the execution time is minimal - no big array operations. reshape doesn't copy data (unless your strides are weird), so it is just the cost of creating a new array object with a shared data pointer.

    Look at the code for np.atleast_2d; it tests for 0d and 1d. In the 1d case it returns result = ary[newaxis,:]. It adds the extra axis first, the more natural numpy location for adding an axis. You add it at the end.

    ar.reshape(ar.shape[0],-1) is a clever way of bypassing the if test. In small timing tests it faster, but we are talking about microseconds, the effect of a function call layer.

    np.column_stack is another function that creates column arrays if needed. It uses:

     if arr.ndim < 2:
            arr = array(arr, copy=False, subok=True, ndmin=2).T
    
    0 讨论(0)
  • 2020-12-08 15:15

    There are mainly two ways to go from 1 dimensional array (N) to 2 dimensional array with 1 column
    (N x 1):

    1. Indexing with np.newaxis;
    2. Reshape with reshape() method.
    x = np.array([1, 2, 3])  # shape: (3,) <- 1d
    
    x[:, None]               # shape: (3, 1) <- 2d (single column matrix)
    x[:, np.newaxis]         # shape: (3, 1) <- a meaningful alias to None
    
    x.reshape(-1, 1)         # shape: (3, 1)
    
    0 讨论(0)
  • 2020-12-08 15:22

    The simplest way:

    ar.reshape(-1, 1)
    
    0 讨论(0)
  • 2020-12-08 15:27

    To avoid the need to reshape in the first place, if you slice a row / column with a list, or a "running" slice, you will get a 2D array with one row / column

    import numpy as np
    x = np.array(np.random.normal(size=(4,4)))
    print x, '\n'
    
    Result:
    [[ 0.01360395  1.12130368  0.95429414  0.56827029]
     [-0.66592215  1.04852182  0.20588886  0.37623406]
     [ 0.9440652   0.69157556  0.8252977  -0.53993904]
     [ 0.6437994   0.32704783  0.52523173  0.8320762 ]] 
    
    y = x[:,[0]]
    print y, 'col vector \n'
    Result:
    [[ 0.01360395]
     [-0.66592215]
     [ 0.9440652 ]
     [ 0.6437994 ]] col vector 
    
    
    y = x[[0],:]
    print y, 'row vector \n'
    
    Result:
    [[ 0.01360395  1.12130368  0.95429414  0.56827029]] row vector 
    
    # Slice with "running" index on a column
    y = x[:,0:1]
    print y, '\n'
    
    Result:
    [[ 0.01360395]
     [-0.66592215]
     [ 0.9440652 ]
     [ 0.6437994 ]] 
    

    Instead if you use a single number for choosing the row/column, it will result in a 1D array, which is the root cause of your issue:

    y = x[:,0]
    print y, '\n'
    
    Result:
    [ 0.01360395 -0.66592215  0.9440652   0.6437994 ] 
    
    0 讨论(0)
  • 2020-12-08 15:29

    You could do -

    ar.reshape(ar.shape[0],-1)
    

    That second input to reshape : -1 takes care of the number of elements for the second axis. Thus, for a 2D input case, it does no change. For a 1D input case, it creates a 2D array with all elements being "pushed" to the first axis because of ar.shape[0], which was the total number of elements.

    Sample runs

    1D Case :

    In [87]: ar
    Out[87]: array([ 0.80203158,  0.25762844,  0.67039516,  0.31021513,  0.80701097])
    
    In [88]: ar.reshape(ar.shape[0],-1)
    Out[88]: 
    array([[ 0.80203158],
           [ 0.25762844],
           [ 0.67039516],
           [ 0.31021513],
           [ 0.80701097]])
    

    2D Case :

    In [82]: ar
    Out[82]: 
    array([[ 0.37684126,  0.16973899,  0.82157815,  0.38958523],
           [ 0.39728524,  0.03952238,  0.04153052,  0.82009233],
           [ 0.38748174,  0.51377738,  0.40365096,  0.74823535]])
    
    In [83]: ar.reshape(ar.shape[0],-1)
    Out[83]: 
    array([[ 0.37684126,  0.16973899,  0.82157815,  0.38958523],
           [ 0.39728524,  0.03952238,  0.04153052,  0.82009233],
           [ 0.38748174,  0.51377738,  0.40365096,  0.74823535]])
    
    0 讨论(0)
  • 2020-12-08 15:32

    A variant of the answer by divakar is: x = np.reshape(x, (len(x),-1)), which also deals with the case when the input is a 1d or 2d list.

    0 讨论(0)
提交回复
热议问题