NumPy 配列の形状変更とサイズ変更

  1. numpy.reshape()
  2. ndarray.reshape()
  3. reshape() 関数/メソッド共有メモリ
  4. numpy.resize()

NumPy には、配列の形状を変更するための 2つの関数(およびメソッド)があります reshaperesize です。これらには大きな違いがあるため、この章で説明します。

numpy.reshape()

配列の形状を変更する関数 reshape() から始めましょう。

import numpy as np

arrayA = np.arange(8)
# arrayA = array([0, 1, 2, 3, 4, 5, 6, 7])

np.reshape(arrayA, (2, 4))
#array([[0, 1, 2, 3],
#       [4, 5, 6, 7]])

8 要素のベクトルを (4, 2) の形状の配列に変換します。形状変更の前後の要素の量が同じであるため、正常に実行できます。数値が異なる場合、ValueError エラーがトリガーされます。

In [1]: np.reshape(arrayA, (3, 4))
    ---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
ValueError: cannot reshape array of size 8 into shape (3,4)

再形成された配列を詳しく見てみましょう。最初の行は arrayA の最初の 4つのデータであり、2 番目の行は最後の 4 を取ります。この形状変換では、行の順序でデータを充填します。

データを充填する順序を列にする場合は、パラメーター order を変更する必要があります。

In [1]: np.reshape(arrayA, (2, 4), order='F')
Out[1]: array([[0, 2, 4, 6],
              [1, 3, 5, 7]])

order のデフォルトは C です。これは、C のようなインデックス順、または単純な単語で、行の順序でデータを読み書きすることを意味します。F は、Fortan のようなインデックス順で、または column の順序でデータを読み書きすることを意味します。さまざまなインデックス方法の詳細については、NumPy の公式ドキュメント を参照してください。

ndarray.reshape()

reshape 関数に加えて、行列形状の変化はデータ darray オブジェクト内の reshpe 方法で行うことができます。メソッドには関数と同じパラメーターがありますが、パラメーターとして指定された配列はありません。

In [1]: arrayB = arrayA.reshape((2, 4))
    
In [2]: arrayB
Out[2]: array([[0, 1, 2, 3],
            [4, 5, 6, 7]])
In [1]: arrayA
Out[2]: array([0, 1, 2, 3, 4, 5, 6, 7])    

使い方は rehape 関数と似ていると見られます。また、ndarray.reshape() メソッドは元の配列のデータと形状を変更せず、新しい ndarray インスタンスを返すことにも注意する必要があります。

reshape() 関数/メソッド共有メモリ

reshape 関数またはメソッドで変換された配列は、元の配列と同じメモリを共有します。Python の shallow copy ように考えることができます。1つの配列のデータを変更すると、他の配列の対応するデータも変更されます。

In [1]: arrayA = np.arange(8)
        arrayB = arrayA.reshape((2, 4))
        arrayB
Out[2]: array([[0, 1, 2, 3],
            [4, 5, 6, 7]])
In [2]: arrayA[0] = 10
        arrayA
Out[2]: array([10, 1, 2, 3, 4, 5, 6, 7]) 
In [3]: arrayB    
Out[3]: array([[10, 1, 2, 3],
            [4, 5, 6, 7]])    

numpy.resize()

numpy.resize() は、形状変換の意味で、reshape に少し似ています。ただし、いくつかの重要な違いがあります。

  1. order パラメーターがありません。resize の順序は reshapeorder='C' と同じです。
  2. ターゲット配列の要素数が元の配列と同じでない場合、サイズ変更を強制しますが、エラーは発生しません。

具体的に 2 番目の違いを見に行きます。

In [1]: arrayA = np.arange(8)
        arrayB = np.resize(arrayA, (2, 4))
Out[1]: array([[0, 1, 2, 3],
       [4, 5, 6, 7]])

要素番号が同じ場合、結果は reshpae の結果と同じです。

In [1]: arrayC = np.resize(arrayA, (3, 4))
        arrayC
Out[1]: array([[0, 1, 2, 3],
       [4, 5, 6, 7],
       [0, 1, 2, 3]])
In [2]: arrayD = np.resize(arrayA, (4, 4))
        arrayD
Out[2]: array([[0, 1, 2, 3],
       [4, 5, 6, 7],
       [0, 1, 2, 3],
       [4, 5, 6, 7]])

新しい配列にさらに行がある場合、元の配列のデータを繰り返しますが、エラーは発生しません。

In [1]: arrayE = np.resize(arrayA, (2, 2))
        arrayE
Out[1]: array([[0, 1],
       [2, 3]])    
In [2]: np.resize(arrayA, (1,4))
Out[2]: array([[0, 1, 2, 3]])

新しい配列の要素の数が少ない場合、元の行列から必要な個数のデータを読み出して、先に行を充填して新しい行列要素に値を付けます。

resize 関数/メソッドのメモリ

新しい配列は、resize 関数/メソッドの元の配列と同じメモリを共有しません。1つの配列のデータ変更は、他の配列にマップされません。

In [1]: arrayA = np.arange(8)
        arrayB = arrayA.reshape((2, 4))
        arrayB
Out[2]: array([[0, 1, 2, 3],
            [4, 5, 6, 7]])
In [2]: arrayA[0] = 10
        arrayA
Out[2]: array([10, 1, 2, 3, 4, 5, 6, 7]) 
In [3]: arrayB    
Out[3]: array([[0, 1, 2, 3],
            [4, 5, 6, 7]])    
comments powered by Disqus