[NumPy] 構造化配列

[NumPy] 構造化配列

 ある統計データを作成するために、人々の名前、年齢、身長などのデータを収集して管理することを考えます。一番素朴な方法は、それぞれのデータを別々の配列に放り込むことです。

 name = np.array(["小春", "小夜子", "時雨"])
 age = np.array([20, 25, 23])
 height = np.array([156.3, 159.8, 162.5])

 しかし、このような形のデータを作ってしまうと、特定の名前でデータを検索したいときに、インデックスを手掛かりに要素を引っ張り出すようなコードを書かなくてはなりません。Python では、この種のデータはディクショナリに格納して管理していましたが、大規模なデータを扱う分析処理においては遅すぎて使い物になりません。

 NumPy では相異なるデータ型をもつ配列(フィールド)を組み合わせて1つの配列として扱うことができます。このような配列を構造化配列 (structured array) とよびます。

 構造化配列を作成するためには、最初に複合データ型を定義しておいて、配列作成時に dtype 引数に渡します。複合データ型を定義する方法は色々ありますが、タプルのリストが一番わかりやすいと思います。以下のサンプルコードを参考にしてください。

# サンプルコード A

# NumPyをインポート
import numpy as np

# 複合データ型の定義
# U12:最大長12のUnicode文字列
# i1:1バイト整数(=np.int8)
# f2:半精度浮動小数点数(=np.float16)
dtype = [("name", "U12"), ("age", "i1"), ("height", "f2")]

# 構造化配列を作成
data = np.zeros(3, dtype = dtype)

# 構造化配列へのデータの書き込み
data["name"] = ["小春", "小夜子", "時雨"]
data["age"] = [20, 25, 23]
data["height"] = [156.3, 159.8, 162.5]

print(data)
[('小春', 20, 156.2) ('小夜子', 25, 159.8) ('時雨', 23, 162.5)]

 データ型の指定には型コードとよばれる短縮形を用いています。
 型コードの最初の文字はデータの種類を表します。
 たとえば、i は整数、f は浮動小数点数を表しています。
 後ろの数字はバイト数です。1 バイト = 8 ビットなので、たとえば "f2" は 16 ビットの浮動小数点数 (np.float16) を表します。もちろん、短縮形を用いずに指定することもできます。

 構造化配列を作っておけば、簡単なコードで色々なデータを取り出すことができます。

# サンプルコード A-1

# 名前の一覧
x = data["name"]

# 身長の一覧
y = data["height"]

# 2人目のデータ
z = data[1]

print("名前", x)
print("身長", y)
print("2人目のデータ", z)
名前 ['小春' '小夜子' '時雨']
身長 [156.2 159.8 162.5]
2人目のデータ ('小夜子', 25, 159.8)

 
 numpy.dtype() を使うと、より複雑な複合データ型をつくることができます。たとえば、次のコードは数値(スカラー)と配列を要素にもつ構造化配列を作成します。

# NumPyをインポート
import numpy as np

# 複合データ型の定義
# i4:32バイト整数(=np.int32)
# f4:単精度浮動小数点数(=np.float32)
d = np.dtype([("x", "i4"), ("y", "f4", (2, 2))])

# 構造化配列を作成
st_a = np.zeros(2, dtype = d)

print(st_a)
[(0, [[0., 0.], [0., 0.]]) (0, [[0., 0.], [0., 0.]])]