NumPy の参照とコピー(三雲勇二の「Puthonによる データ分析の教科書 第二版」を初心者向けに 解説してみたコラム)

みなさん、こんにちは。 エンジニアをしております、三雲と申します。

私はたまにですが初心者にプログラミングについて教えたりすることがあります。
特に Python は人気で、理由として『データ分析』が簡単に行えるところで興味を持たれる方が多いようです!
データ分析というと少し難しそうに感じるかもしれませんが、Python を使うと思ったよりも簡単に行なえます。
この機会に試してみてはいかがでしょうか?

今回は紙書籍版Pythonによるあたらしいデータ分析の教科書 第2版(翔泳社)では、p.102 〜 p.105 の部分になります。

テーマは「NumPy の参照とコピー」です。

せっかくですので私も初心に戻り、新人エンジニアやこれからエンジニアを目指している方の「Python でデータ分析を勉強してみよう!」という視点で、分かりやすい記事になればと思います。
どうぞよろしくお願いいたします。

目次

そもそも NumPy とは

NumPy は Python の数値計算のためのライブラリであり、高度な数値計算機能を提供しています。
NumPy の主な機能は、多次元配列(ndarray)オブジェクトをサポートすることで、これにより数値データの効率的で高速な操作を可能にします。

少し難しい言い回しになってしまいましたが、Python のリストより高度な計算が素早く行えるライブラリということみたいです。

NumPy のもう一つの特徴として、多くの Python のライブラリの基礎部分として使用されるため、他のライブラリと一緒にインストールされることが多いです。
それほど非常に便利なパッケージなので、Python でプログラミングする方は NumPy の使い方を覚えておいて損はないです。

NumPy は pip でインストールできます。
Pythonによるあたらしいデータ分析の教科書 第2版(翔泳社)で使用するバージョンは p.50 にあるとおりのものを指定しましょう。
バージョンによって、使用できるメソッドや引数など変更がある場合がありますので、書籍通りのバージョンをインストールすることが重要です。
書籍通りに動かない場合、よくよく調べてみると「書籍のバージョンと異なるバージョンがインストールされていたことが原因だった」というケースもありますので、ご注意ください。

pip install numpy==1.22.4

NumPy を使うにはパッケージをインポートしておく必要がありますので、忘れずにしておきましょう。

import numpy as np

Python の『参照』と『コピー』の違いを復習

Python 変数に値を代入する際に、参照が作成される場合と、値のコピーが作成される場合とがあります。
改めて確認してみましょう。

まず、『参照』について確認しましょう。

少し難しい説明になってしまいますが、参照とは変数に代入されたオブジェクトのメモリ上のアドレスを指します。
つまり、参照を持つ変数は、そのオブジェクトのメモリ上の場所を示しているだけで、そのオブジェクト自体を保持しているわけではありません。

以下のコードを例にあげます。

a = [1, 2, [3, 4, 5]]
b = a

この場合、変数 b は変数 a が指すリストオブジェクトのメモリ上の場所を指す参照を持っています。
つまり、ab は同じオブジェクトを指しています。
したがいまして、a または b のどちらかを変更すると変更内容が両方の変数に反映されます。

![[Pythonデータ分析コラム/三雲インターネットアカデミー様_Python3データ分析第1回/attachments/python3da_1_assignment.png]]

次に、『コピー』について確認しましょう。

こちらも少し難しい説明になってしまいますが、コピーとは変数に代入されたオブジェクトを複製して新しいオブジェクトを作成することを指します。
つまり、コピーを持つ変数は、別のメモリ上のオブジェクトを保持しています。
Python では、浅いコピー深いコピーと呼ばれる2種類のコピーがあります。

『浅いコピー』とは、オブジェクトのコピーを作成しますが、コピーされたオブジェクトの内部に含まれる他のオブジェクトについては、参照がコピーされます。
したがって、浅いコピーを持つ変数は、コピーされたオブジェクト自体を保持していますが、その内部に含まれるオブジェクトについては、元のオブジェクトと同じメモリ上の場所を指しています。

以下のコードを例にあげます。

a = [1, 2, [3, 4, 5]]
b = a.copy()

この場合、変数 b は変数 a をコピーしますが、[3, 4, 5] (この部分を仮に c とする) のリスト部分は参照として複製されます。
つまり、ab は異なるリストオブジェクトを指し示していますが、c の部分は参照となるため共有されてしまいます。

![[Pythonデータ分析コラム/三雲インターネットアカデミー様_Python3データ分析第1回/attachments/python3da_1_shallow_copy.png]]

『深いコピー』とは、オブジェクトのコピーをすべて作成します。
通常のコピーとしてイメージしやすいのはこの動作かと思います。

以下のコードを例にあげます。

a = [1, 2, [3, 4, 5]]
b = copy.deepcopy(a)

この場合、変数 b は変数 a 全体をコピーします。

![[Pythonデータ分析コラム/三雲インターネットアカデミー様_Python3データ分析第1回/attachments/python3da_1_deep_copy.png]]

なお、変数に代入された値の参照を作成することを「参照渡し」と呼び、コピーを作成することを「値渡し」と呼ぶこともあります。

NumPy の参照とコピー

NumPy モジュールでは、参照やコピーはどの様になっているのでしょうか。

reval メソッドと flatten メソッドがあるので試してみましょう。

import numpy as np

a = np.array([[11, 12, 13], [21, 22, 23]])
b = a.ravel()
c = a.flatten()

同じ結果が返ってきました。

# b : reval()
array([11, 12, 13, 21, 22, 23])

# c : flatten()
array([11, 12, 13, 21, 22, 23])

では、元の a 配列を操作してみます。

a[0][1] = 123

今度は結果が変わりました。

# b : reval()
array([11, 123, 13, 21, 22, 23])

# c : flatten()
array([11, 12, 13, 21, 22, 23])

reval メソッドは参照され、flatten メソッドはコピーされていました。
なお、NumPy では flatten メソッドは深いコピーとして設定されています。

今回のまとめ

Python の基礎の復習まとめです。
Python のコピーには次のものがあります。

  • 参照:値を持っている場所をコピーする
  • コピー:値自体をコピーする
    • 浅いコピー:コピーされた内部のオブジェクトは参照がコピーされる
    • 深いコピー:すべての内容がコピーされる

今回 NumPy で使用したメソッドと、参照とコピーの関係は次のとおりです。

  • 参照:reval メソッド
  • 浅いコピー:(今回該当なし)
  • 深いコピー:flatten メソッド

参照とコピーの選び方ですが、基本的に参照のほうが高速かつメモリの使用量が少ないです。
コピーをしなければならない場合は、範囲を絞り込んで小さくコピーするなど考えると、処理速度が早くなると思います。
参照とコピーの違いをきちんと把握して、NumPy を高速に正しく使い分けられるようになりたいものです。

今回のコラムはいかがでしたでしょうか?
インターネットアカデミーでは Python 講座が充実しています。
Python 認定スクールにもなっているため、質の良い知識を得ることができます。
基礎を習得した先に新たな目標を設定し、目指していくために大変良い場所となります。

「プログラミングは独学でもなんとかなる」という情報もありますが、新しいことを学んでいく際の近道は「プロに教えてもらうこと」かと思います。
インターネットアカデミーはキャリアサポートも充実しており、一人ひとりに専任のキャリアプロデューサーがサポートしてくれるため中途半端になることがありません。
ご興味ある方は各講座のページを覗いてみてください。無料カウンセリングもできます。

Pythonの基礎からDjangoフレームワークを使ったWebアプリケーションを作りたい方向けの「Python講座」

Pythonを活用したAIプログラミング、機械学習を実装したい方向けの「AIプログラミング講座」

良い記事だなって思ったら、是非シェアをお願いします!
  • URLをコピーしました!
  • URLをコピーしました!
目次