多次元配列

目的

ここまではnumpyモジュールのndarrayオブジェクトを使用した1次元配列の扱い方を学んだ.機械学習で使用するデータやビッグデータは,多次元配列として表現されることが多く,ndarrayオブジェクトは多次元配列を表現することができる.ここでは,最も単純な多次元配列である2次元配列の扱い方を通して多次元配列について学ぶ.

説明

2次元配列の生成

まず2次元配列の作り方を見てみよう.

5行目のように大括弧を2重にし,各要素をカンマで区切ることによって2次元配列を生成することができる.この場合生成される2次元配列は,3つの要素をもつ配列が2つある構造となっている.

配列オブジェクトの変数

1次元配列と2次元配列を生成し,配列オブジェクトのいくつかの変数を表示させて,構造の違いを確認しよう.

配列オブジェクトの変数ndimには次元数が格納されており,10,11行目のように記述すれば,配列の次元数を参照することができる.また,配列オブジェクトの変数sizeには要素数が保存されており,13,14行目のように記述すると,配列の要素数を確認することができる.さらに,変数shapeには配列の形(shape)が格納されており,16行目のように記述すると,3つの要素をもつ1次元配列を表す「(3,)」が,17行目のように記述すると,3つの要素をもつ配列が2つあることを表す「(2, 3)」を参照することができる.配列のshapeはタプルとして表現されており,19から21行目のように記述することで,shapeの各要素を参照することができる.

2次元配列の要素の参照

2次元配列の各要素をインデックス番号で参照するには,以下のように記述すればよい.

7行目から13行目のように,配列オブジェクト名の後に大括弧で囲んで,外側の要素のインデックス番号と内側の要素のインデックス番号をカンマ区切りで記述すると,2次元配列の各要素の値を参照することができる.

zeros, ones, full, empty関数による2次元配列の生成

zeros関数・ones関数・full関数・empty関数は2次元配列を生成する際にも使用できる.

5行目から8行目のように,zeros, ones, full, empty関数の引数として2次元配列のshapeを表すタプルを指定すると,指定したshapeをもつ2次元配列を生成することができる.

shapeの変更(reshape)

1次元配列を2次元配列に変更するには,shapeを変更すればよい.

6行目のように,numpyモジュールのreshape関数を,reshapeしたい配列・reshape後のshapeを引数として指定して呼び出すと,reshapeされた配列が返される.また,7行目のように,配列オブジェクトのreshapeメソッドを,reshape後のshapeを引数として呼び出す場合もreshapeされた配列が返される.

また,12行目のように,元の1次元配列の要素の値を変更すると,reshapeした2次元配列の要素の値も変更されていることから,これらは同じオブジェクトを指していることがわかる.

reshapeする場合は,変更前と変更後の配列の要素数が同じでなければならない.

5行目のように6個の要素をもつ1次元配列を,6行目のように(2,4)のshapeの2次元配列にreshapeしようとすると,要素数が6個と8個で異なるため,以下のようなエラーメッセージが表示される.

このようなことを避けるために,reshape関数・reshapeメソッドでは,shapeを指定するタプルで-1の値を指定することができる.

6行目のように(2,-1)と指定すると,6個の要素を(2,3)のshapeに,7行目のように(-1,2)と指定すると,6個の要素を(3,2)のshapeに変更できる.

sizeの変更(resize)

配列のreshapeとよく似た機能に配列のresizeがある.

5行目のように6個の要素をもつ1次元配列を生成し,7行目のように,numpyモジュールのresize関数を,resizeしたい配列・resize後のshapeを引数として指定して呼び出すと,resizeされた配列が返される.resize前と後で配列の要素数が同じ場合はreshape関数と同様である.では,resize前の要素数よりresize後の要素数が多い場合の例を確認しよう.7行目のように記述すると,足りない分の要素には,元の配列の要素が繰り返されて保存される.また,8行目のように,resize前の要素数がresize後の要素数より多い場合は,多い分は無視されてresizeされる.

また,14行目のように,元の1次元配列の要素の値を変更しても,resizeした2次元配列の要素の値は変更されていないことから,これらは別のオブジェクトであることがわかる.

また,配列のresizeは配列オブジェクトのresizeメソッドを使用してもでき,この場合は新しい配列オブジェクトは生成されず,元の配列オブジェクトの構造が変更される.

6行目のように6個の要素をもつ1次元配列arrayを生成し,7行目のようにresizeすると,配列オブジェクトarray自体がresizeされる.9行目のように,resize前の要素数よりresize後の要素数が多い場合,足りない分の要素には0が保存される.また,11行目のように,resize前の要素数がresize後の要素数より多い場合,多い分は無視されてresizeされる.

平坦化(ravel)

2次元配列を1次元配列にする際にもreshapeやresizeを使用することができるが,ravel関数やravelメソッドを使用することもできる.

6行目のように,numpyモジュールのravel関数を2次元配列を引数で指定して呼び出すと,平坦化された1次元配列が返される.また,7行目のように,配列オブジェクトのravelメソッドを呼び出しても,平坦化された1次元配列が返される.

12行目のように,元の2次元配列のある要素の値を変更すると,平坦化した1次元配列の要素の値も変更されていることから,これらは同じオブジェクトを指していることがわかる.

平坦化(flatten)

2次元配列を1次元配列にするもう1つの方法として,flattenメソッドを使用する方法がある.

6行目のように,配列オブジェクトのflattenメソッドを呼び出すと,平坦化された1次元配列が返される.

10行目のように,元の2次元配列のある要素の値を変更すると,平坦化した1次元配列の要素の値は変更されてないことから,これらは別のオブジェクトであることがわかる.

2次元配列のスライス

2次元配列の一部をスライスして取り出すには,外側の要素をスライスし,カンマで区切って内側の要素をスライスするように記述すればよい.

7行目のように記述すると,外側の要素のインデックス番号1から3の部分で,内側の要素のインデックス番号が3から6の部分が取り出せる.

多次元配列

多次元配列の作り方や要素の値の参照の仕方もルールは2次元配列と同様である.

課題

課題0

ある学生の英語・数学・国語のテストの点数と,別のある学生の英語・数学・国語のテストの点数からなる2次元配列を作成せよ.

課題1

ある学生の3回分の英語のテストの点数と,3回分の数学のテストの点数と,3回分の国語のテストの点数と,3回分の理科の点数と,3回分の社会の点数からなる2次元配列を作成せよ.

課題2

学生Aの英語・数学・国語のテストの点数と,学生Bの英語・数学・国語のテストの点数からなる2次元配列を作成し,Aの英語の点数と,Bの数学の点数を表示せよ.

課題3

ある学生の3回分の英語のテストの点数と,3回分の数学のテストの点数と,3回分の国語のテストの点数と,3回分の理科の点数と,3回分の社会の点数からなる2次元配列を作成し,1回目の英語の点数と,2回めの社会の点数と,3回目の国語の点数を表示せよ.

課題4

shapeが(20,10)で要素の値が全て0の配列を作成せよ.

課題5

shapeが(10,20)で要素の値が全て1の64ビット整数の配列を作成せよ.

課題6

shapeが(10,10)で要素の値が全て適当な値の8ビット符号なし整数の配列を作成せよ.

課題7

学生300人の5教科(英語・数学・国語・理科・社会)のテストの点数からなるshapeが(300,5)の2次元配列を作成し,300人の国語の点数を取り出せ.

課題8

学生300人の10回分のテストの点数からなるshapeが(300,10)の2次元配列を作成し,ある学生(例えば100人目)の3回目から8回目のテストの点数を取り出せ.

課題9

学生300人の10回分の5教科(英語・数学・国語・理科・社会)のテストの点数からなるshapeが(300,10,5)の3次元配列を作成し,偶数番目の学生の5回目から10回目の英語・数学・国語の点数を取り出せ.