ビューとコピー

5.5. ビューとコピー#

配列の実態にはビューview) とコピーcopy)の 2 種類があります。配列を生成したあと、その配列の一部を取り出した部分配列や、np.ravel などの関数で形状を変えた配列は、見かけ上形は異なりますが、データを格納しているメモリを共有しています。このような配列を元の配列のビューと呼びます。

メモリを共有しているため、ビューの値を変更すると、元の配列の値も変更されます。

x = np.array([[1, 2, 3, 4],
              [5, 6, 7, 8]])
a = np.ravel(x)

a[0:4] = 0
x
array([[0, 0, 0, 0],
       [5, 6, 7, 8]])

逆に、元の配列 x の要素を変更すると、その変更はビュー a にも反映されます。

x[1, :] = -1
a
array([ 0,  0,  0,  0, -1, -1, -1, -1])

このように、ビューは同じデータを共有しているため、片方を変更するともう片方にも影響が出ます。

一方、コピーは元の配列とは独立した別の配列です。コピーを作成するには、配列の copy メソッドを使います。例えば、先ほどの np.ravel で作成したビューに対して .copy() を呼び出すと、コピーが作成されます。コピーに対して値を変更しても、元の配列のデータは変更されません。

x = np.array([[1, 2, 3, 4],
                [5, 6, 7, 8]])
a = np.ravel(x)
b = a.copy()
b[0:4] = 0
x
array([[1, 2, 3, 4],
       [5, 6, 7, 8]])
x[1, :] = -1
b
array([0, 0, 0, 0, 5, 6, 7, 8])

また、次のように、配列の構造を変換した直後に copy をつけて、1 行で済ますこともできます。

x = np.array([[1, 2, 3, 4],
              [5, 6, 7, 8]])
a = np.ravel(x).copy()
a
array([1, 2, 3, 4, 5, 6, 7, 8])

コピーしたつもりがビューだった。気づかず喜んでたら、卒業要件ひとつ消えてた。ビューの取り扱い、人生より慎重に。