NumPy 配列作成の基本テクニック

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

はじめに

事前準備

このコースを開始する前に、基本的な Python プログラミングスキルが必要です。まだ Python を学習していない場合は、Python 学習パスから始めることができます。

NumPy 配列の基本的な作成テクニックに関する実験へようこそ。コーディングを開始する前に、NumPy とは何か、そして科学計算においてなぜ NumPy が不可欠なのかを理解しましょう。

NumPy とは?

NumPy(Numerical Python の略)は、Python における科学計算の基本的なライブラリです。数値データの大きな配列や行列を扱うための強力なデータ構造と関数を提供します。

Python リストではなく NumPy を使用する理由

Python の組み込みリストは柔軟で使いやすいですが、数値データを扱う際にはいくつかの制限があります。

  • パフォーマンス: NumPy 配列は数学的な演算において格段に高速です。
  • メモリ効率: NumPy は同じ量のデータを格納するのに、より少ないメモリを使用します。
  • 利便性: NumPy は数百もの組み込み数学関数を提供します。
  • 機能性: NumPy は行列乗算、フーリエ変換などの高度な操作をサポートします。

この実験では、NumPy 配列を作成するための最も一般的な方法を学びます。Python シーケンスの変換、組み込み NumPy 関数の使用、既存の配列の操作、ファイルからのデータ読み込みを練習するために、Python スクリプトを作成して実行します。すべてのコーディングは WebIDE 内で行われます。

Python シーケンスからの配列作成

NumPy 配列を作成する最も基本的な方法は、リストやタプルなどの Python シーケンスを変換することです。numpy.array()関数は、シーケンスを引数として受け取り、新しい NumPy 配列を返します。

NumPy 配列の理解

配列を作成する前に、NumPy 配列が特別である理由を理解しましょう。

配列の次元

  • 1 次元配列(ベクトル): [1, 2, 3, 4]のような単純な数値のリスト
  • 2 次元配列(行列): スプレッドシートのように、行と列を持つ数値のテーブル
  • 3 次元配列(テンソル): 画像や 3D データに便利な数値の立方体

Array Dimensions

Python リストとの主な違い

  • 均一性: すべての要素は同じデータ型(通常は数値)である必要があります。
  • 固定サイズ: 作成後はサイズを変更できません。
  • 効率性: 数学的な演算がはるかに高速です。
  • 豊富な機能: ベクトル化された操作(配列全体に対する一度の操作)をサポートします。

NumPy のインポート

Python では、標準的なエイリアスnpを使用して NumPy をインポートします。

import numpy as np

このnpエイリアスは、科学計算 Python コミュニティで広く採用されている慣習です。

それでは、いくつかの配列を作成しましょう。左側のファイルエクスプローラーからarray_from_sequence.pyファイルを開きます。以下のコードを追加してください。このコードは、NumPy ライブラリをインポートし、Python リストから 1 次元(1D)、2 次元(2D)、3 次元(3D)配列を作成します。

Python code to create NumPy arrays

import numpy as np

## リストから 1D 配列を作成
a1D = np.array([1, 2, 3, 4])
print("1D Array:")
print(a1D)

## リストのリストから 2D 配列を作成
a2D = np.array([[1, 2], [3, 4]])
print("\n2D Array:")
print(a2D)

## ネストされたリストから 3D 配列を作成
a3D = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print("\n3D Array:")
print(a3D)

提案: 上記のコードをコードエディタにコピーし、各コード行を注意深く読んでその機能を理解してください。さらに詳しい説明が必要な場合は、「コードの説明」ボタン👆をクリックしてください。Labby と対話して、パーソナライズされたヘルプを得ることができます。

コードを追加したら、ファイルを保存します。次に、ターミナルからスクリプトを実行して出力を確認します。

python array_from_sequence.py

作成した配列を表示する以下の出力が表示されるはずです。

1D Array:
[1 2 3 4]

2D Array:
[[1 2]
 [3 4]]

3D Array:
[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]

データ型(dtype)の理解

NumPy 配列は、すべての要素に対して固定のデータ型を持ち、これはdtypeパラメータで指定されます。これは、各要素が異なる型を持つことができる Python リストとは異なります。

データ型が重要な理由

  • メモリ効率: 異なる型は異なる量のメモリを使用します。
  • パフォーマンス: 操作は特定のデータ型に対して最適化されています。
  • 精度: 数値の格納方法と計算方法を制御します。

一般的なデータ型

  • int32 / int64: 整数(32 ビットまたは 64 ビット)
  • float32 / float64: 小数(32 ビットまたは 64 ビット)
  • complex: 複素数
  • bool: True/False値

dtypeパラメータを使用して配列を作成する際にデータ型を指定できます。例:np.array([1, 2], dtype=complex)。dtype を指定しない場合、NumPy は入力データに基づいて適切な dtype を自動的に選択します。

組み込み配列作成関数の使用

NumPy には、Python シーケンスを必要とせずに、ゼロから配列を作成するための組み込み関数がいくつか用意されています。これらの関数は特定のユースケースに最適化されており、リストから手動で配列を作成するよりもはるかに高速です。

これらの関数を使用する理由

np.array([0, 0, 0, 0, 0]) と書く代わりに、単に np.zeros(5) を使用できます。これらの関数は以下の利点があります。

  • 高速: 内部で最適化された C コードを使用しています。
  • 可読性が高い: 関数名から意図が明確です。
  • メモリ効率が良い: 直接メモリ割り当てを行います。
  • 便利: 各要素を手動で指定する必要がありません。

intrinsic_creation.py ファイルを開き、以下のコードを追加してください。このスクリプトは、いくつかの一般的な生成関数を示しています。

import numpy as np

## 要素の範囲から配列を作成
## np.arange(start, stop, step) - Python の range() に似ています
## ユースケース:ループ用のシーケンス作成、インデックス生成
arr_range = np.arange(0, 10, 2)  ## [0, 2, 4, 6, 8]
print("Array from arange:")
print(arr_range)

## 2 点間の指定された数の要素を持つ配列を作成
## np.linspace(start, stop, num_elements) - 等間隔の点
## ユースケース:プロット用の点の作成、データのサンプリング
arr_linspace = np.linspace(0, 10, 5)  ## 0 から 10 までの 5 点
print("\nArray from linspace:")
print(arr_linspace)

## ゼロで埋められた配列を作成
## np.zeros((rows, columns)) - 計算用の配列を初期化
## ユースケース:計算された値で埋める前に配列を事前割り当て
arr_zeros = np.zeros((2, 3))  ## ゼロの 2x3 配列
print("\nArray of zeros:")
print(arr_zeros)

## 1 で埋められた配列を作成
## np.ones((rows, columns)) - 1 で初期化
## ユースケース:マスク、スケーリング係数、またはアルゴリズムの開始点の作成
arr_ones = np.ones((3, 2))  ## 1 の 3x2 配列
print("\nArray of ones:")
print(arr_ones)

## 単位行列を作成
## np.eye(size) - 対角線上に 1、それ以外は 0 の正方行列
## ユースケース:線形代数、変換のリセット、行列乗算
identity_matrix = np.eye(3)  ## 3x3 の単位行列
print("\nIdentity matrix:")
print(identity_matrix)

ファイルを保存し、ターミナルから実行します。

python intrinsic_creation.py

出力には、これらの関数によって作成されたさまざまな配列が表示されます。

Array from arange:
[0 2 4 6 8]

Array from linspace:
[ 0.   2.5  5.   7.5 10. ]

Array of zeros:
[[0. 0. 0.]
 [0. 0. 0.]]

Array of ones:
[[1. 1.]
 [1. 1.]
 [1. 1.]]

Identity matrix:
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

既存の配列の操作

既存の配列を変更、結合、または分割することによって、新しい配列を作成することもできます。このセクションでは、「ビューとコピー」および「配列の連結」という 2 つの重要な概念について説明します。

ビューとコピー:メモリ共有の理解

これは、初心者によく混乱をもたらす NumPy の最も重要な概念の 1 つです。

ビューとは?

ビューは、メモリ内の同じデータを異なる方法で見ることです。ビューを作成する(スライシングなどを介して)場合、新しい配列を作成しているのではなく、既存のデータへの新しい参照を作成しているだけです。

コピーとは?

コピーは、メモリ内に独自のデータを持つ完全に新しい配列を作成します。コピーへの変更は元の配列に影響を与えず、その逆も同様です。

なぜこれが重要なのか

  • ビューはメモリ効率が良い: データを複製しません。
  • ビューは高速: コピーのオーバーヘッドがありません。
  • しかし、ビューは予期しない副作用を引き起こす可能性があります: ビューを変更すると元のデータも変更されます。
  • コピーはより安全: 変更は分離されますが、より多くのメモリを使用します。

また、複数の配列を 1 つのより大きな配列に結合する方法も探求しましょう。

array_manipulation.py ファイルを開き、以下のコードを追加してください。

import numpy as np

## --- Part 1: Views vs. Copies ---
a = np.arange(1, 5)
print("Original array 'a':", a)

## 最初の 2 つの要素のビューを作成
b = a[:2]
b[0] = 99 ## ビューを変更
print("Modified view 'b':", b)
print("Array 'a' after modifying the view:", a) ## 'a' も変更されます

## コピーを作成
c = a[:2].copy()
c[0] = 0 ## コピーを変更
print("\nModified copy 'c':", c)
print("Array 'a' after modifying the copy:", a) ## 'a' は変更されません

## --- Part 2: Joining Arrays ---
A = np.ones((2, 2))
B = np.eye(2) * 2
C = np.zeros((2, 2))
D = np.diag((-3, -4))

## 配列をブロック行列に結合
block_matrix = np.block([
    [A, B],
    [C, D]
])
print("\nBlock matrix:")
print(block_matrix)

ファイルを保存し、ターミナルから実行します。

python array_manipulation.py

出力は、ビューの変更が元の配列にどのように影響するかを示し、コピーの変更はそうではないことを示します。また、4 つの小さな配列を 1 つのブロック行列に結合した結果も示します。

Original array 'a': [1 2 3 4]
Modified view 'b': [99  2]
Array 'a' after modifying the view: [99  2  3  4]

Modified copy 'c': [0 2]
Array 'a' after modifying the copy: [99  2  3  4]

Block matrix:
[[ 1.  1.  2.  0.]
 [ 1.  1.  0.  2.]
 [ 0.  0. -3.  0.]
 [ 0.  0.  0. -4.]]

ファイルからの配列読み込み

データ分析における一般的なタスクは、ファイルを NumPy 配列にロードすることです。NumPy は、大規模なデータセットを効率的に読み込み、適切な数値形式に自動的に変換できるため、このタスクに優れています。

ファイル I/O に NumPy を使用する理由

  • 速度: Python で一行ずつ読み込むよりもはるかに高速です。
  • 型推論: 適切なデータ型を自動的に検出します。
  • メモリ効率: データを最適化された配列に直接ロードします。
  • 利便性: 複雑な解析ではなく、単一の関数呼び出しで済みます。

一般的なファイル形式

  • CSV ファイル: カンマ区切り値(最も一般的)
  • TSV ファイル: タブ区切り値
  • テキストファイル: スペースまたはカスタム区切り文字で区切られたファイル
  • バイナリファイル: 非常に大きなデータセット用(高度)

CSV(Comma-Separated Values)のような単純なテキストファイルの場合、NumPy はnp.loadtxt()関数を提供します。

この実験(Lab)のセットアップスクリプトは、プロジェクトディレクトリにdata.csvという名前のファイルを既に作成しています。その内容は以下の通りです。

col1,col2,col3
1.0,2.5,3.2
4.5,5.0,6.8
7.3,8.1,9.9

次に、read_from_file.pyファイルを開き、このデータを読み込むために以下のコードを追加してください。

np.loadtxt のパラメータを理解する

np.loadtxt()関数には、いくつかの重要なパラメータがあります。

  • delimiter=',': 列の区切りを指定します(CSV の場合はカンマ)。
  • skiprows=1: 最初の行(通常はヘッダー)をスキップします。
  • dtype: オプション - データ型を指定します(指定しない場合は自動検出されます)。
  • usecols: オプション - 読み込む列を指定します。
  • comments: オプション - 行を無視するためのコメント文字を指定します。

ここでは、delimiter=','を使用して列がカンマで区切られていることを指定し、skiprows=1を使用してヘッダー行を無視します。

import numpy as np

## CSV ファイルからデータをロード
try:
    ## 相対パスは検証に失敗するため、実験では絶対パスを使用してください
    data = np.loadtxt('/home/labex/project/data.csv', delimiter=',', skiprows=1)
    print("Data loaded from data.csv:")
    print(data)
except IOError:
    print("Error: data.csv not found.")

ファイルを保存し、ターミナルから実行します。

python read_from_file.py

スクリプトはdata.csvから数値データを読み込み、NumPy 配列として表示します。

Data loaded from data.csv:
[[1.  2.5 3.2]
 [4.5 5.  6.8]
 [7.3 8.1 9.9]]

この方法は、構造化された数値データを配列にロードしてさらに処理するのに非常に効率的です。

まとめ

この実験では、NumPy 配列を作成するための基本的なテクニックを学びました。Python リストからの配列作成、np.arangenp.zeros のような組み込み関数の使用、ビュー、コピー、結合による既存配列の操作、そして np.loadtxt を使用したテキストファイルからのデータ読み込みを実践しました。

これらのスキルは、Python で実行するほぼすべての数値計算および科学計算タスクの構成要素となります。配列作成に関する確かな理解を得たことで、NumPy におけるより高度な配列操作や数学的演算を探求する準備が整いました。