NumPy

【NumPy】NumPyのndarrayとPython組み込み型のlistとの違い ~なぜ分析でndarrayを使うのか~

【NumPy】NumPyのndarrayとPython組み込み型のlistとの違い _なぜ分析でndarrayを使うのか_

Pythonでデータ分析をする際にはNumPyパッケージをよく使用します。NumPyの中でもndarray型を使用しますが、Pythonの組み込み型のlistと何が違うのでしょうか。本記事ではNumPyのndarrayとPython組み込み型のlistの違いを説明し、なぜ分析でNumPyのndarrayを使用するのかを解説したいと思います。

NumPyのndarray型とPython組み込み型のlist型

Pythonでデータ分析等を行う際にはNumPyのndarray型をよく使用します。以下のコードでもわかるようにlist型を使用してndarray型を作成することができます。

import numpy as np

# list型
data = [1, 2, 3, 4, 5]
print(type(data))

# ndarray型
array_data = np.array(data)
print(type(array_data))
【実行結果】
<class 'list'>
<class 'numpy.ndarray'>

どちらも連続するシーケンスデータを扱うという意味では同じものであるので、わざわざNumPyのndarray型にしなくても「Pythonの組み込み型のlist型を分析で使用してもいいではないか」と思うかと思います。

結論を先に述べると「NumPyのndarray型の方がPython組み込み型のlistよりも大量のデータを高速に処理できるように設計されているため、大量のデータ分析にはNumPyのndarray型が適切である」ということになります。

以降では、関連する情報を順に説明していこうかと思います。

Note

私は最初NumPyを学んだ時にarrayとndarrayという言葉の違いについてごちゃごちゃになっていました。array型?ndarray型?みたいに思ってしまっていました。

正確にはNumPyで使用する型をndarray型といい、ndarray型を生成する関数がarray関数ですので覚えておきましょう。

Pythonの型の理解を深める

Pythonは動的型付け言語

Pythonは動的型付け言語として知られており、明確に型を指定する必要がありません。過去にCやJAVAなどを経験されたことがある人にとっては、初めてPythonに触れると少し気持ち悪いと感じるかもしれません。

(私も大学時代はC/C++、最初に就職した会社はC#やJAVAという経験でしたので、Pythonを最初に学んだ時には、型を指定しないことに違和感を覚えましたが、Pythonに触れていくうちにだんだんと慣れました。)

例えば、C言語でリストに値を入れたい場合には、以下のように型を宣言して使用しますが、その後に異なる型の値を代入しようとするとエラーとなります。

int x = 1;
x = "sample_text";    // <- ERROR

一方で、Pythonでは同じようなコードを書いたとしてもエラーにはなりません。このように、Pythonは実行時に型を自動で理解して適切に利用できるようにしてくれます。

x = 1
x = 'sample_text'

Pythonの型はC言語での構造体となっている

標準的なPythonの言語自体はC言語を使って実装されています(CPythonと言います)。他にもJavaで実装されているJythonなどもありますが、以降はCPythonを基本に説明をしていきます。

例えば、int型について考えてみます。PythonでいうところのintはC言語でのただのintとは少し違います。PythonのintはC言語の構造体として定義されていて、intの値の他にも色々な情報を保有しています。以下が、Pythonでのintのイメージ図です。

C言語のint Pythonのint 違い

上記はあくまでイメージですのでご注意ください。Pythonはデータの値だけではなくヘッダーの情報として色々な情報を持っている構造体となっています。このことは、C言語のintに比べてPythonのintの方が蓄積に要するオーバーヘッドが大きいということを意味します。

Pythonのlistは任意の型の値で構成できる

次にPythonのリストを見てみます。Pythonのリストでは以下の例のように、複数の型の値を持つリストというものを定義できます。

data = [0, '1', True, 2.0]
data_types = [type(d) for d in data]

print(data)
print(data_types)
【実行結果】
[0, '1', True, 2.0]
[<class 'int'>, <class 'str'>, <class 'bool'>, <class 'float'>]

普通は数値なら数値のリスト、文字列なら文字列のリストというように同じ型で使う方がほとんどであると思いますので、あまりこのような使用方法をする人はいないかと思います。

ある型のみで使用するlistはPythonのリスト型としては一部の使用例となっているということを理解していただければよいかと思います。

PythonのlistとNumPyのndarrayの違い ~なぜ分析でndarrayを使うのか~

効率的なデータ構造となっている

NumPyのndarrayとPython組み込み型のlistではデータの持ち方の構造が異なっています。NumPyのndarrayとPython組み込み型のlistのイメージの違いは以下のようなイメージです。

numpyのndarrayとPython組み込み型のlist

上記はイメージなので実装レベル正確さとは異なる場合がある点はご注意ください。

ndarrayの場合は、連続するデータブロックの一つのポインタのみを持つような形となります。一方でPython組み込み型のlistは上記のintの例で見たようなPythonオブジェクトへのポインターのリストというような構造をとっています。

データのアクセス性を考えた場合、連続するブロックにある方が効率的で、データのサイズが大きくなるほどその差は顕著になります。このようにndarray型の方が効率的な構造となっています。

豊富なデータ操作のメソッドがたくさんある

NumPyのndarrayの特徴としては、データ操作のためのメソッドが豊富にある点があげられます。 ndarrayの公式ドキュメントの記載はこちらを参考にしてください。

ドキュメントのMethodsというところを見ていただくと分かりますがデータ操作のためのメソッドが豊富に用意されています。また、機械学習エンジンであるscikit-learn等もNumPyのndarrayをベースにしているため、NumPyに慣れておくことは重要です。

Note

Pythonでarray型という型を制限した型があります。

import array

data = list(range(10))
array_data = array.array('i', data)
print(array_data)
【実行結果】
array('i', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

この例では、’i’ = int型に制限しているので、文字列を入力するとエラーになります。array型はlistに比べると効率のよい型ですが、NumPyのndarrayの方が各種データ操作のメソッドが用意されている等、複雑なデータ分析ではndarrayを使う方が適切と考えています。

arrayの公式ドキュメントの記載はこちらを参照してください。