NumPy 配列属性

この章では、NumPy 配列のいくつかの基本属性について学んでいきます。

NumPy 配列の次元数はランク(rank)と呼ばれ、ランクとは軸の数のこと、つまり配列の次元です。

1次元配列のランクは 1、2次元配列のランクは 2、以下同様です。

NumPy では、配列の各次元は軸(axis)、すなわち次元(dimensions)と呼ばれます。

例えば、2次元配列は「1次元配列から構成される1次元配列」と見なせます。外側の配列の各要素自体がまた1次元配列です。

ここで、第0軸は最も外側の配列の方向に相当し、第1軸は内側の配列の方向で、以下同様です。

軸の数、すなわちランクが、配列の次元数です。

多くの NumPy 関数は axis 引数をサポートしています。

2次元配列の場合、axis=0 は第0軸に沿って操作することを意味し、つまり各列に対して操作します。axis=1 は第1軸に沿って操作することを意味し、つまり各行に対して操作します。

以下では、shape が (2, 3) の2次元配列を例に、2つの軸の方向と各属性の意味を直感的に示します。

axis = 1:水平方向の矢印 axis = 1(第1軸) 水平方向、各行に沿って axis = 0:垂直方向の矢印 axis = 0(第0軸) 垂直方向、各列に沿って 列インデックス 列 0 列 1 列 2 行インデックス 行 0 行 1 2×3 グリッド 1 2 3 4 5 6 行と shape カードの点線の関連 shape の説明カード shape = (2, 3) 2 → 第0軸の長さ(行数) 3 → 第1軸の長さ(列数) 下部の属性まとめ ndim = 2(軸の数、すなわちランク)・ size = 2 × 3 = 6(要素の総数)

axis は「どの方向に圧縮するか」を表しており、「何行目/何列目」ではありません。axis=0 に沿った合計は複数の行を1行に圧縮するため、結果は各列の合計になります。

例

import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])

# 第0軸に沿って合計:行方向に圧縮し、各列の合計を求める
print(a.sum(axis=0))

# 第1軸に沿って合計:列方向に圧縮し、各行の合計を求める
print(a.sum(axis=1))

出力結果は次のとおりです:

[5 7 9]
[ 6 15]

以下のインタラクティブなデモで、2つの軸の合計方向をより直感的に確認できます。ボタンをクリックして切り替えてください:

↓↓↓
1
2
3
4
5
6
5
7
9
→
6
→
15
a.sum(axis=0) → [5 7 9]、第0軸に沿って各列の要素を1つの数に圧縮する

NumPy 配列の中で比較的重要な ndarray オブジェクトの属性は次のとおりです:

属性説明
ndarray.ndim配列のランク(rank)。すなわち配列の次元数または軸の数です。
ndarray.shape配列の次元。配列の各軸上のサイズを表します。2次元配列(行列)の場合、行数と列数を表します。
ndarray.size配列内の要素の総数。次に等しい:ndarray.shapeshape の各軸上のサイズの積。
ndarray.dtype配列内の要素のデータ型。
ndarray.itemsize配列内の各要素のサイズ(バイト単位)。
ndarray.flagsメモリレイアウトに関する情報を含みます。C または Fortran の連続したストレージであるか、読み取り専用であるかなどです。
ndarray.real配列内の各要素の実部(要素の型が複素数の場合)。
ndarray.imag配列内の各要素の虚部(要素の型が複素数の場合)。
ndarray.data配列要素を実際に格納するバッファ。通常はインデックスで要素にアクセスし、この属性を直接使用することはありません。

ndarray.ndim

ndarray.ndim は、配列の次元数(つまり配列の軸数)、すなわちランクを取得するために使用します。

例

import numpy as np

a = np.arange(24)
print(a.ndim)             # a は現在1次元のみ

# reshape でサイズを調整し、2ページ・4行・3列にする
b = a.reshape(2, 4, 3)    # b は現在3次元
print(b.ndim)

出力結果は次のとおりです:

1
3

ndarray.shape

ndarray.shape は配列の次元を表し、タプルを返します。このタプルの長さが次元の数、すなわち ndim 属性(ランク)です。

例えば、2次元配列の shape はその「行数」と「列数」を表します。

shape タプルの順序は軸の順序と一致します。第0要素は第0軸のサイズ(行数)、第1要素は第1軸のサイズ(列数)です。

例

import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.shape)

出力結果は次のとおりです:

(2, 3)

ndarray.shape は配列のサイズ調整にも使用できます。

例

import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])
a.shape = (3, 2)
print(a)

出力結果は次のとおりです:

[[1 2]
 [3 4]
 [5 6]]

NumPy には、配列のサイズを調整するための reshape 関数も用意されています。

例

import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])
b = a.reshape(3, 2)
print(b)

出力結果は次のとおりです:

[[1 2]
 [3 4]
 [5 6]]

2つの方法の違い:a.shape に直接代入すると配列 a 自体がその場で変更されます。一方、a.reshape(3, 2) は新しい配列オブジェクトを返し(通常は a とデータを共有します)、a 自体は変更されません。


ndarray.size

ndarray.size は、配列内の要素の総数を返します。これは shape の各軸上のサイズの積に等しいです。

例

import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.shape)   # shape は (2, 3)
print(a.size)    # 要素の総数:2 × 3 = 6

出力結果は次のとおりです:

(2, 3)
6

ndarray.dtype

ndarray.dtype は、配列内の要素のデータ型を返します。

dtype オブジェクトには、型名や要素のビット幅などの情報が含まれます。例えば、int64 は64ビット整数、float32 は32ビット浮動小数点数を表します。

例

import numpy as np

# 整数リストからはデフォルトで int64 配列が作成されます(Windows ではデフォルトで int32)
a = np.array([1, 2, 3])
print(a.dtype)

# 作成時に dtype 引数でデータ型を明示的に指定できます
b = np.array([1, 2, 3], dtype=np.float32)
print(b.dtype)

出力結果は次のとおりです:

int64
float32

ndarray.real と ndarray.imag

ndarray.real と ndarray.imag は、それぞれ配列内の各要素の実部と虚部を返します。主に要素の型が複素数(complex)の場合に使用します。

例

import numpy as np

# 複素数配列を作成、デフォルトの型は complex128
a = np.array([1+2j, 3+4j, 5+6j])
print(a.real)   # 各要素の実部
print(a.imag)   # 各要素の虚部

出力結果は次のとおりです:

[1. 3. 5.]
[2. 4. 6.]

ndarray.itemsize

ndarray.itemsize は、配列内の各要素のサイズをバイト単位で返します。

例えば、要素の型が float64 の配列の場合、itemsize 属性の値は 8 です(float64 は64ビットを占有し、8ビットが1バイトなので、64 ÷ 8 = 8バイト)。

また、要素の型が int32 の配列の場合、itemsize 属性の値は 4 です(32 ÷ 8)。

size と itemsize の積が、配列データが占める合計バイト数、すなわち ndarray.nbytes 属性の値です。

例

import numpy as np

# 配列の dtype は int8、各要素は1バイト
x = np.array([1, 2, 3, 4, 5], dtype=np.int8)
print(x.itemsize)

# 配列の dtype は float64、各要素は8バイト
y = np.array([1, 2, 3, 4, 5], dtype=np.float64)
print(y.itemsize)

出力結果は次のとおりです:

1
8

ndarray.flags

ndarray.flags は ndarray オブジェクトのメモリ情報を返し、次の属性を含みます:

属性説明
C_CONTIGUOUS (C)データが単一の C 言語スタイルの連続したメモリ領域にある
F_CONTIGUOUS (F)データが単一の Fortran 言語スタイルの連続したメモリ領域にある
OWNDATA (O)配列が使用するメモリを所有しており、他のオブジェクトから借用していない
WRITEABLE (W)データ領域に書き込み可能。この値を False に設定すると、データは読み取り専用になる
ALIGNED (A)データとすべての要素がハードウェアに対して適切にアラインされている
WRITEBACKIFCOPY (X)この配列は他の配列のコピーであり、この配列が解放されると、その内容は元の配列に書き戻される

旧バージョンの UPDATEIFCOPY (U) は WRITEBACKIFCOPY の旧名称で、NumPy 1.14 で非推奨となり、NumPy 2.0 以降では完全に削除されたため、現在は使用すべきではありません。

C_CONTIGUOUS と F_CONTIGUOUS は、同一のデータがメモリ内でどのように並んでいるかを表します。同じ2次元配列には2つの典型的な格納方法があります:

左側:C言語スタイル(行優先) C言語スタイル(行優先) まず0行目を格納してから、1行目を格納する 123 456 格納順序のインデックス:行ごとに1〜6 1 2 3 4 5 6 行ごとに順に展開する メモリ配置:1 2 3 4 5 6 123 456 1 2 3 4 5 6 012 345 メモリアドレス(左から右へ) C_CONTIGUOUS : True 右側:Fortran言語スタイル(列優先) Fortran言語スタイル(列優先) まず0列目を格納してから、1列目を格納する 123 456 格納順序のインデックス:列ごとに1〜6 1 2 3 4 5 6 列ごとに順に展開する メモリ配置:1 4 2 5 3 6 142 536 1 2 3 4 5 6 012 345 メモリアドレス(左から右へ) F_CONTIGUOUS : True 下部の説明 NumPy配列はデフォルトでC言語スタイル(行優先)で格納される

例

import numpy as np

x = np.array([1, 2, 3, 4, 5])
print(x.flags)

出力結果は:

  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
その他の拡張