ねこすたっと

ねこの気持ちと統計について悩む筆者の備忘録的ページ。

チュートリアル拾い読み (1):NumPy公式チュートリアル (1/5) [Python]

Rもたいして使いこなせてないのにPythonの勉強を始めてみました。色々と素晴らしいチュートリアルはありそうですが、目移りしてしまうので公式チュートリアルを拾い読みしていきます。

現時点でのチュートリアル拾い読みのモットーは、

  • 正確さよりも分かりやすさ*1
  • 説明のために別の記事へ飛ばない*2

です。

初回は、NumPy公式チュートリアルの "NumPy: the absolute basics for beginners" をPython初心者目線での疑問を交えながら読んでいきます。

NumPyから始める理由

チュートリアルの冒頭で、 「NumPyはあらゆる科学・工学分野における数値計算の基礎となるライブラリである」 と説明されています。

大抵の場合、基礎は退屈です。多分NumPyもそう。 でもある程度の読み書きが出来ないことには楽しい話は読めませんので、まずは我慢ですね…。

ライブラリ(library)の読み込み

Pythonはライブラリを読み込むことで機能を拡張することが出来ます。NumPyもライブラリの1つです。

NumPyライブラリの機能を使うためには、まず読み込む必要があります。下のコードで読み込みましょう。

import numpy as np

as npは「以後、numpyのことはnpと呼びますね」という意味です。毎回長いライブラリ名が出てくると、読みにくいし書きにくいからです。

エラーが出る場合、使用しているPythonにNumPyライブラリがインストールされていないことが原因かもしれません。PC音痴の私にはこの初期設定のハードルがめちゃくちゃ高かったです。ひとまずGoogle Colabを使えば回避できますが、問題の先送りなだけかも(いずれ物足りなくなる日が来る!?)。

配列(array)

NumPyは、複数のデータを配列として持つことで効率的で高速な計算を可能にしてくれます。「配列とは何か」の前に、Pythonで複数データがどのように保持されるかを見てみます。

Pythonで複数データを保持するための基本構造

Pythonで複数のデータを保持するための基本的なデータ構造には次のようなものがあります。

リスト以外の詳細は、それが登場したときにまた見ていきます。

配列(array)とは

配列は前述のリスト(list)と同じように複数の項目(item)を順番に保持していますが、配列では保持している値のデータ型が全部同じでなければなりません。リストはバラバラでもOKです。

そしてややこしい話ですが、Pythonでは配列にも2種類あるようです。

1つはPython標準ライブラリにあるarrayオブジェクト*3です。これは1つの方向に並ぶ配列(1次元配列)しか扱えません。

もう1つは今回勉強中のNumPyライブラリにあるndarrayオブジェクトです。これは多次元配列(N-dimensional array)、つまり縦・横・奥行き…といった多方向に広がる配列を扱うことができます

両者ともデータの型が揃っていないといけない点は同じです。以降、配列と言えばndarrayのことだと思ってください。

配列を作ってみる

リストをNumPyのarray( )関数に渡して配列にしてもらいます。 この関数がNumPyライブラリの中に含まれていることを示すために、np(最初に宣言したnumpyの略)の後に.をつけてarray( )を書きます。

Rだと::で呼び出し元のパッケージを示しますが、Rの場合は関数名が競合している注意が表示されるだけで、パッケージ名をいちいち明示しなくても通じます。

a = np.array([1, 2, 3])
print(a)

出力は

[1 2 3]

出力がシンプルすぎて、ちゃんとできているのか不安になります。type( )で確認してみます。

type(a)  # 出力: numpy.ndarray

確かにndarray形式の配列になっていました。

ちなみに、#は「これ以降はコメントであって、コードではないですよ」という記号です。毎回「出力は」と書くと余白が多くなるので、セルの中に#出力と書きましたが、実際に実行してもこのコメントが一緒に出力されるわけではありません。

配列の次元(dimension)と形状(shape)

配列が広がっている方向のことを次元、あるいは軸(axis)と言います。1方向に並んでいるだけなら1次元配列(1-D array)、縦横2方向に広がっているなら2次元配列(2-D array)です。多次元配列(N-D array)は次元数を一般化した言い方です。

高校数学を学んだ後であれば、ベクトルとか行列といった呼び方の方が馴染みがあるかもしれません。ベクトル(vector)は1次元配列、行列(matrix)は2次元配列のことです。3次元以上の多次元配列はテンソル(tensor)と呼ばれます。

それぞれの軸の方向に箱が何個並んでいるかを表したものを配列の形状(shape)と言います。例えば、上図真ん中の2次元配列の形状は、(3, 4) となります。

多次元の配列を作ってみる

入れ子構造になった「リストのリスト」をnp.array( )に渡して、print( )で表示させてみます。

a = np.array([[1, 2, 3, 4], 
              [5, 6, 7, 8], 
              [9, 10, 11, 12]])
print(a)

# 出力
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]

print( )なしでaとだけ打っても表示はされるんですが、Jupyter Notebookでセル単位で実行するときにprint( )がないと最後の出力しか表示されません。

配列のデータ型・次元・形状を確認する

a = np.array([[1, 2, 3, 4], 
              [5, 6, 7, 8], 
              [9, 10, 11, 12]])

上記で作成した配列aの後に、以下のコードを追加することでaの情報を取り出すことができます。

  • .dtype:データの型
  • .ndim:次元数
  • .shape:形状
  • .size:全要素数

例えば、形状であれば

a.shape  # 出力: (3, 4)

となります。ちなみに、1次元の場合でも、(3,)のように丸カッコ付きで結果が返ってきます。

これらの配列aの特徴に関する情報は属性(attribute)と呼ばれます。ndarrayという鋳型(クラス)を使って作られたもの(インスタンス)には、これらの属性を持つようにあらかじめ設計されているので、a以外の配列でも同じ方法(.shapeなど)で属性を呼び出すことができます。

余談ですが、ライブラリ名を書くときに続き、また.が出てきました。 初めて見たときに、この2つがどういうルールで同じ.を使っているのか分からず悩んだことがあります。 両者とも「〜の中の」という階層構造を表していると考えれば意味が通じそうです。

  • NumPyライブラリの中にあるarray( )関数
  • ndarrayオブジェクトの中にあるshape属性

配列の形状を変更する

先程作成した配列aの配列の形状を変更するためには、.reshape( )というコードをaの後に追加します。

a.reshape(2,6)
# 出力: 
array([[ 1,  2,  3,  4,  5,  6],
       [ 7,  8,  9, 10, 11, 12]])

形状が(2, 6)の配列に作り替えられました。

ここで登場した.reshape( )メソッド(method)と言われるもので、「属性」が対象の特性であったのに対し、「メソッド」は対象に対する処理です。 属性と同様、ndarrayという鋳型(クラス)を使って作られたもの(インスタンス)は、このような処理を受け付けることが前もって設計されているので、a以外の配列でも同じ方法で.reshape( )などの処理を行うことができます。

おわりに

今回学んだこと:

  • NumPyでは多次元配列を扱うライブラリである
  • 配列の作り方
  • 配列の次元・形状とその確認方法
  • 属性とメソッド

チュートリアルは読んだけど取り上げなかったもの:

  • np.zeros( ):要素が全て0の配列を作る関数
  • np.ones( ):要素が全て1の配列を作る関数
  • np.empty( ):要素がランダムに与えられる配列を作る関数
  • np.arange( ):連続する数値からなる配列を作る関数
  • np.linspace( ):等間隔の値を持つ配列を作る関す
  • np.sort( ):配列を順に並べ替えた配列を返す関数。a.sort( )というメソッドとしても利用可能。
  • np.concatenate( ):複数の配列を結合して1つの配列にする関数
  • np.newaxis:既存の配列に新しい次元を追加するときに使うもの
  • np.expand_dims( ):指定した軸に新しい次元を追加する関数

次回:

necostat.hatenablog.jp

*1:あやふやな書き方に対する言い訳です

*2:寄り道迷子になるのを防ぐためです。上手くリンクを構築する手間を惜しんでいるわけではありません。

*3:「オブジェクト」の詳細は別の機会に勉強するとして、ここでは「そういう型のもの」の意味で理解しておきましょう