NumPyの操縦ndarrayの形状

5714 ワード

シリーズ記事
一度にNumPyの入門基礎知識NumPyの操縦ndarrayの形状NumPyの浅いコピーと深いコピーNumPyのインデックステクニックを完成する
概要
ここでは主にndarray形状に対する3つの操作をまとめます.
  • ndarrayの形状を変更する
  • いくつかのndarray
  • を積み重ねます
  • 分割ndarray
  • ndarrayの形を変える
    次のndarrayを例に挙げます.
    >>> a = np.floor(10*np.random.random((3,4)))
    >>> a
    array([[ 2.,  8.,  0.,  6.],
           [ 4.,  5.,  1.,  1.],
           [ 8.,  9.,  3.,  6.]])
    >>> a.shape
    (3, 4)    
    

    次の3つは、ndarrayのシェイプを変更する3つの一般的なコマンドです.この3つのコマンドは、元のndarrayを変更しないことに注意してください.
    >>> a.ravel()  #    ndarray     ndarray   
    array([ 2.,  8.,  0.,  6.,  4.,  5.,  1.,  1.,  8.,  9.,  3.,  6.])
    
    >>> a.reshape(6,2)  #     shape,    shape ndarray
    array([[ 2.,  8.],
           [ 0.,  6.],
           [ 4.,  5.],
           [ 1.,  1.],
           [ 8.,  9.],
           [ 3.,  6.]])
    
    >>> a.T  #       ndarray,             
    array([[ 2.,  4.,  8.],
           [ 8.,  5.,  9.],
           [ 0.,  1.,  3.],
           [ 6.,  1.,  6.]])
    >>> a.T.shape
    (4, 3)
    >>> a.shape
    (3, 4)  
    

    なお、上記のいくつかのコマンドは、形状を変更する際に従う原則が「C-style」である.つまり、右端のインデックスは、最も速く変化します.a.ravel()を例にとると、a[0][0]の後に続く元素はa[0][1]である.NumPyの内部記憶もこの順序に従うため、ravel()を使用してもコピーの動作は起こらない.もちろん、ravel()およびreshape()は、パラメータによって制御することができ、例えば「FORTRAN−style」を用いたモードを変更して、最左のインデックスを最も速くすることができる.
    次の2つの方法の違いに注意してください.reshapeは新しいndarrayを返し、resizeはこのndarray自体を直接修正します.
    >>> a
    array([[ 2.,  8.,  0.,  6.],
           [ 4.,  5.,  1.,  1.],
           [ 8.,  9.,  3.,  6.]])
    >>> a.resize((2,6))
    >>> a
    array([[ 2.,  8.,  0.,  6.,  4.,  5.],
           [ 1.,  1.,  8.,  9.,  3.,  6.]]) 
    
    reshapeのパラメータが-1の場合、reshapeの最終形状は関数によって自動的に計算されます.
    >>> a.reshape(3,-1)
    array([[ 2.,  8.,  0.,  6.],
           [ 4.,  5.,  1.,  1.],
           [ 8.,  9.,  3.,  6.]]) 
    

    ndarrayのスタック
    いくつかの異なるndarrayは、指定されたaxisに沿ってスタックできます.たとえば、次のようになります.
    >>> a = np.floor(10*np.random.random((2,2)))
    >>> a
    array([[ 8.,  8.],
           [ 0.,  0.]])
    >>> b = np.floor(10*np.random.random((2,2)))
    >>> b
    array([[ 1.,  8.],
           [ 0.,  4.]])
    
    >>> np.vstack((a,b))
    array([[ 8.,  8.],
           [ 0.,  0.],
           [ 1.,  8.],
           [ 0.,  4.]])
    
    >>> np.hstack((a,b))
    array([[ 8.,  8.,  1.,  8.],
           [ 0.,  0.,  0.,  4.]])    
    

    上記の例では、2次元ndarrayを例にとると、vstack法は垂直方向に積み重ね(すなわち、第1のaxis)、hstack法は水平方向に積み重ね(すなわち、第2のaxis)である.column_stackの方法は、2つの1 Dのndarrayについて、それらを2 Dのndarrayに積層することに注意してください.例:
    >>> a = np.array([1,2,3])
    >>> b = np.array([4,5,6])
    >>> np.column_stack((a,b))
    array([[1, 4],
           [2, 5],
           [3, 6]])
    

    2 Dのndarrayの場合、column_stackの役割はhstackに等しく、そうでなければhstackは2つの1 Dのndarrayを行として統合します.
    >>> from numpy import newaxis
    >>> a = np.floor(10*np.random.random((2,2)))
    >>> b = np.floor(10*np.random.random((2,2)))
    >>> np.column_stack((a,b))    
    array([[ 8.,  8.,  1.,  8.],
           [ 0.,  0.,  0.,  4.]])
    >>> a = np.array([4.,2.])
    >>> b = np.array([3.,8.])
    >>> np.column_stack((a,b))     
    array([[ 4., 3.],
           [ 2., 8.]])
    >>> np.hstack((a,b))           #     ,  hstack   1D ndarray         
    array([ 4., 2., 3., 8.])
    >>> a[:,newaxis]               #   axis
    array([[ 4.],
           [ 2.]])
    >>> np.column_stack((a[:,newaxis],b[:,newaxis]))
    array([[ 4.,  3.],
           [ 2.,  8.]])
    >>> np.hstack((a[:,newaxis],b[:,newaxis]))   #         
    array([[ 4.,  3.],
           [ 2.,  8.]])  
    

    一方、row_stackは、いつでもvstackと同等である.要約すると、2次元以上のndarrayについては、hstackが2番目のaxisに沿ってマージされ、vstackが1番目のaxisに沿ってマージされ、concatenateがパラメータ制御により、どの方向に沿ってマージされるかが決定される.
    さらに、いくつかの複雑なシーンでは、以下のように、r_およびc_を使用してndarrayを作成することができる.
    >>> np.r_[1:4,0,4]
    array([1, 2, 3, 0, 4])
    

    その中の:arangeの方法の中の意味と同じです.ここで、r_およびc_の役割は、それぞれvstackおよびhstackの役割と類似しているが、パラメータ制御によって、どのaxisに沿ってスタックされるかを決定することも可能である.
    あるaxisに沿ってスタックする場合、スタックに参加するndarrayの他のaxisのlengthは同じである必要があります.例えば、1つのndarrayは、別のndarrayと第1のaxisに沿ってスタックすることができるが、別のndarrayと第1のaxisに沿ってスタックすることはできない.
    ndarrayの分割
    1つのndarrayはいくつかの小さなndarrayに分割することができます.ここで、hsplitを例にとると、この関数はndarrayを水平方向に分割することができる.2つの方法でパラメータを渡すことができます.1つは、パラメータNを指定し、元のndarrayをいくつかの小さなndarrayに分割することを説明し、NumPyはこのパラメータに基づいて、この方向に沿って元のndarrayなどをN部に分割する(列数がNで割り切れない場合は、エラーを報告する).もう1つは、どの列の後ろでナイフを切るかを指定し、NumPyはこの指示に従って元のndarrayを分割します.
    たとえば、6列のndarrayについて、パラメータ3が入力されると、NumPyは、同じndarrayを等分します.パラメータ(1,3)が入力されると、NumPyは対応する列の後ろに線(第1列の後ろ、第3列の後ろ)を引いて分割します.
    コードの例は次のとおりです.
    >>> a = np.floor(10*np.random.random((2,12)))
    >>> a
    array([[ 9.,  5.,  6.,  3.,  6.,  8.,  0.,  7.,  9.,  7.,  2.,  7.],
           [ 1.,  4.,  9.,  2.,  2.,  1.,  0.,  6.,  2.,  2.,  4.,  0.]])
    >>> np.hsplit(a,3)   # Split a into 3
    [array([[ 9.,  5.,  6.,  3.],
           [ 1.,  4.,  9.,  2.]]), array([[ 6.,  8.,  0.,  7.],
           [ 2.,  1.,  0.,  6.]]), array([[ 9.,  7.,  2.,  7.],
           [ 2.,  2.,  4.,  0.]])]
    >>> np.hsplit(a,(3,4))   # Split a after the third and the fourth column
    [array([[ 9.,  5.,  6.],
           [ 1.,  4.,  9.]]), array([[ 3.],
           [ 2.]]), array([[ 6.,  8.,  0.,  7.,  9.,  7.,  2.,  7.],
           [ 2.,  1.,  0.,  6.,  2.,  2.,  4.,  0.]])]