[NumPy超入門]インデックスやスライスなどを使って多次元配列「ndarray」を操作してみようPythonデータ処理入門(1/2 ページ)

ndarrayオブジェクトはさまざまな形で操作できます。今回はその基本となる形状の変更、四則演算、インデックスとスライスによる要素選択と値の変更を見ていきます。

» 2023年07月07日 05時00分 公開
[かわさきしんじDeep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「Pythonデータ処理入門」のインデックス

連載目次

 前回はNumPyが提供する多次元配列であるnumpy.ndarrayを紹介しました(以下、ndarrayとします)。今回はその要素を取り出したり、その値を変更したりする方法を見ていきます。

ndarrayの形状を変更してみよう

 前回にお話した内容とかぶるところもありますが、まずはndarrayの特徴をまとめておきましょう。

ndarrayオブジェクトの特徴

  • ndarrayオブジェクトはさまざまな方法で作成できる(numpy.array関数、numpy.arange関数など)
  • 1つのndarrayオブジェクトに格納できるデータの種類は全て同じ
  • ndarrayオブジェクトの要素にはインデックスを用いてアクセスする
  • Pythonのリストなどと同様に、スライスを指定して複数の要素にアクセスすることも可能
  • ndarrayオブジェクトの次元数、形状、全要素数はそれぞれndim属性、shape属性、size属性で調べられる
  • 全要素数が変わらなければ、その次元数や形状は変更できる(reshapeメソッド、numpy.reshape関数)

numpy.linspace関数

 この後で使用するために、ここでは1次元の配列を作成しておきます。ただし、前回に使ってみたnumpy.array関数とnumpy.arange関数とは別のnumpy.linspace関数を使ってみましょう。

 numpy.linspace関数の構文を以下に示します。

numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)

numpy.linspace関数

 パラメーターは以下の通りです。

  • start:生成する配列の初期値(複数要素を持つリストや配列を指定することも可能。本稿では割愛)
  • stop:生成する配列の最終値(複数要素を持つリストや配列を指定することも可能。本稿では割愛)
  • num:要素数。startとstopで指定される範囲を分割する要素の数
  • endpoint:生成する配列にstopで指定した値を含めるかどうか
  • retstep:生成された配列と一緒に公差(要素間の間隔)を返送するかどうか
  • dtype:配列の要素のデータ型
  • axis: start/stopにリストや配列を渡したときに、生成される配列をどのように格納するかを指定する(本稿では割愛)

 簡単にいえば、startとstopで示される範囲をnumで指定された数の要素で分割するのがnumpy.linspace関数です。Pythonのrange関数やnumpy.arange関数とは異なり、初期値/最小値/公差を指定するのではない点には注意しましょう。また、デフォルトでは生成される配列にはstopに指定した最終値が含まれる点にも注意です。

 以下に簡単な使用例を示します。

import numpy as np

a = np.linspace(0.0, 0.5, 6)
print(a)  # [0.  0.1 0.2 0.3 0.4 0.5]

numpy.linspace関数の使用例

 これは0.0から0.5の範囲を6つの要素で分割した配列を生成します(5等分して、その初期値と最終値が0.0と0.5になります)。

 前回のおさらいとなりますが、ここで生成された1次元配列の次元数、形状、要素数を調べてみましょう。それぞれndim属性、shape属性、size属性で得られます。

print(a.ndim)  # 1
print(a.shape)  # (6, )
print(a.size)  # 6

生成された1次元配列の次元数、形状、要素数を表示

ndarrayオブジェクトの形状を変更してみる

 上で作成したのは1次元の配列でしたが、ndarrayオブジェクトはその形状を変更できます。つまり、1次元配列を2次元配列にしたり、3次元配列にしたりできるということです。ただし、要素数は変わらないので、6つの要素からなる上の配列は2行3列の行列にすることはできても、2行4列の行列に変更することはできません。

 形状を変更するには、ndarrayオブジェクトが持つreshapeメソッドを使うか、numpy.reshape関数を使用するか、ndarrayオブジェクトのshape属性の値を変更します。

 reshapeメソッドとnumpy.reshape関数の基本構文を以下に示します(詳細な構文は上記のリンクを参照のこと)。

ndarray.reshape(newshape)
numpy.reshape(a, newshape)

ndarray.reshapeメソッドとnumpy.reshape関数

 numpy.reshape関数では第1引数に形状を変更したいndarrayオブジェクトを指定します。両者に共通のnewshapeには整数か整数を要素とするタプルを指定します。それが変更後の形状を表します。2次元配列(行列)にするのであれば、例えば「(2, 3)」のように指定すればよいでしょう。

 以下に例を示します。

b = a.reshape((2, 3))
print(b)

b = np.reshape(a, (2, 3))
print(b)

# 出力結果は同じ
#[[0.  0.1 0.2]
# [0.3 0.4 0.5]]

reshapeメソッドとnumpy.reshape関数による形状の変更

 この例ではnewshapeに「(2, 3)」と指定しているので、2行3列の行列へと形状が変更されます。出力結果を見ると、そのことが分かりますね。

 ここでは行と列の数を全て指定しましたが。行数が分かれば列数も自動的に決定する(その逆も同じ)ことに着目してください。このように、明示的に指定をしなくてもよいときにはそこに「-1」を記述することが可能です。以下に例を示します(出力結果は上と同じなので省略)。

b = a.reshape((-1, 3))  # 行の要素数は列の要素数から計算されて2になる
print(b)

b = np.reshape(a, (2, -1))  # 列の要素数は行の要素数から計算されて3になる
print(b)

-1を指定した次元については要素数は自動的に計算される

 この場合は、行と列のどちらかの要素数が決定されれば、もう一方の要素数も決まりますが、3次元の配列(テンソル)については2つの次元の要素数が決定しなければ、残りの次元の要素数が分かりません。形状を変更する際に「-1」を指定できるのは1つの次元だけということには注意しましょう。

 最後にshape属性を使った形状の変更についても例を示しておきます。

print(b.shape)  # (2, 3)

b.shape = (3, 2# 3行2列の配列に形状を変更
print(b.shape)  # (3, 2)
print(b)
# 出力結果:
#[[0.  0.1]
# [0.2 0.3]
# [0.4 0.5]]

b.shape = (6,)  # 6行の1次元配列に形状を変更
print(b.shape)  # (6,)
print(b)  # [0.  0.1 0.2 0.3 0.4 0.5]

shape属性による形状の変更

 2つのメソッド/関数でnewshapeに指定したものと同様な値をshape属性にセットしているだけなので、特に説明の必要はないでしょう。

 ここではndarrayオブジェクトを操作する手始めにその形状を変化させてみました。

ndarrayオブジェクトの加減乗除

       1|2 次のページへ

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。