NumPy における構造化配列

NumPyBeginner
オンラインで実践に進む

はじめに

この実験では、NumPy の構造化配列について学びます。構造化配列は、データベースのテーブルやスプレッドシートに似た、異種データを扱うための強力な機能です。構造化配列の各要素は、"フィールド" と呼ばれる名前付きの列を持つ行と考えることができます。これにより、Python 内で直接表形式データを整理および操作するのに理想的です。

この実験全体を通して、WebIDE で提供される structured_arrays.py ファイルに Python コードを記述し、実行します。

構造化配列の作成とアクセス

まず、簡単な構造化配列を作成しましょう。構造化配列のデータ型 (dtype) は、タプルのリストとして定義されます。各タプルは、その (名前, データ型) を指定します。これにより、同じ配列内に文字列や整数などの異なるデータ型を格納できます。

左側のパネルにあるファイルエクスプローラーから structured_arrays.py ファイルを開きます。以下のコードを追加して、名前と年齢を持つ人々のリストを表す構造化配列を作成します。

## Create a structured array
data = np.array([('Alice', 25, 55.5), ('Bob', 30, 68.0)],
                dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')])

print("Original Array:")
print(data)

## Access a specific field by its name
names = data['name']
print("\nNames field:")
print(names)

コードの説明:

  • import numpy as np: NumPy ライブラリをインポートします。
  • np.array([...], dtype=[...]): 配列を作成します。最初の引数はタプルのリストで、各タプル ('Alice', 25, 55.5) がデータの 1 行を表します。
  • dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')]: ここが重要な部分です。3 つのフィールドを定義します。
    • 'name': 最大 10 文字の Unicode 文字列 (U10)。
    • 'age': 4 バイト (32 ビット) の整数 (i4)。
    • 'weight': 4 バイト (32 ビット) の浮動小数点数 (f4)。
  • data['name']: フィールド名(列名)をインデックスとして使用することで、特定のフィールド(列)のすべての値にアクセスでき、新しい NumPy 配列が返されます。

ファイルを保存し、ターミナルから実行して出力を確認してください。

python structured_arrays.py

以下の出力が表示され、完全な構造化配列と名前のみを含む配列が表示されます。

Original Array:
[('Alice', 25, 55.5) ('Bob', 30, 68. )]

Names field:
['Alice' 'Bob']

フィールドの変更とインデックス参照

構造化配列はミュータブル(変更可能)であり、その値を変更できます。フィールド全体を一度に変更したり、インデックスで特定の要素にアクセスしてからそのフィールドを変更したりできます。元のフィールドのサブセットを含む新しい配列を作成することもできます。

structured_arrays.py スクリプトの末尾に以下のコードを追加してください。

## Modify the 'age' field
data['age'] = [26, 31]
print("\nArray after modifying age:")
print(data)

## Access a single element (the first row)
first_person = data[0]
print("\nFirst person's data:")
print(first_person)

## Create a new array with a subset of fields
subset = data[['name', 'weight']]
print("\nSubset of array (name and weight):")
print(subset)

コードの説明:

  • data['age'] = [26, 31]: これは、age フィールドに新しい値のリストを割り当て、列全体を更新します。
  • data[0]: これは、配列の最初の要素(行)にアクセスします。結果は NumPy の void スカラーとなり、その単一行のデータを保持します。
  • data[['name', 'weight']]: フィールド名のリストを渡すことで、複数の列を選択でき、それらのフィールドのみを持つ新しい構造化配列が作成されます。

ファイルを保存し、再度ターミナルから実行してください。

python structured_arrays.py

出力には新しいセクションが含まれ、変更された配列とサブセットが表示されます。

... (previous output) ...

Array after modifying age:
[('Alice', 26, 55.5) ('Bob', 31, 68. )]

First person's data:
('Alice', 26, 55.5)

Subset of array (name and weight):
[('Alice', 55.5) ('Bob', 68. )]

レコード配列を使用した属性アクセス

名前によるインデックス参照(例:data['name'])は強力ですが、冗長になることがあります。NumPy は ndarray の特殊なサブクラスであるレコード配列 (np.recarray) を提供しています。レコード配列を使用すると、フィールドを属性としてアクセスでき、ドット記法(例:record_array.name)を使用できるため、コードをよりきれいで読みやすくすることができます。

レコード配列は直接作成することも、既存の構造化配列を変換することもできます。両方の方法を見てみましょう。structured_arrays.py の末尾に以下のコードを追加してください。

## Convert the structured array to a record array using view()
record_array = data.view(np.recarray)

print("\nType of the new view:")
print(type(record_array))

## Access fields using attribute (dot) notation
print("\nAccessing names via attribute:")
print(record_array.name)

print("\nAccessing ages via attribute:")
print(record_array.age)

コードの説明:

  • data.view(np.recarray): .view() メソッドは、同じデータを参照する新しい配列オブジェクトを作成します。np.recarray を指定することで、構造化配列データのレコード配列ビューを取得します。データはコピーされず、単にそれと対話するための別の方法です。
  • record_array.name: これがレコード配列の主な特徴です。name フィールドにオブジェクトの属性であるかのようにアクセスできます。これは record_array['name'] と同等です。

ファイルを保存して実行してください。

python structured_arrays.py

出力には新しい配列ビューのタイプが表示され、属性アクセスが実証されます。

... (previous output) ...

Type of the new view:
<class 'numpy.recarray'>

Accessing names via attribute:
['Alice' 'Bob']

Accessing ages via attribute:
[26 31]

まとめ

この実験では、NumPy で構造化配列を使用するための基本を学びました。まず、名前付きフィールドと複数のデータ型を持つ構造化配列を作成しました。次に、辞書スタイルのキーインデックスを使用して特定のフィールド(列)にアクセスし、その値を変更する練習をしました。最後に、レコード配列という便利な代替手段を調査しました。これにより、フィールドに属性としてアクセスでき、.view() メソッドを使用して標準の構造化配列とレコード配列の間で変換する方法を学びました。

構造化配列は、Python を使用した科学計算およびデータ分析において、複雑な表形式データセットを処理するための不可欠なツールです。