Python♪NumPyのa[[0], 0, 0:1]は何次元の配列になる?

NumPyの配列の要素はスライスやリスト(配列)を使って部分的に要素を抜き出せますが、抜き出した配列の次元がどうなるのか混乱しませんか?しかし、実は抜き出し後の配列の次元数は機械的に判断できます。最初に知っておくと頭に入りやすくなります。

1.要素を整数で指定する場合

まず、最初に要素のインデックス番号を整数で指定する場合の規則性を説明します。何次元の配列になるのかについてはコード01の15~23行目の右側にコメント文を追加しました。

要素を整数で直接指定する場合の規則性として、要素を指定した数だけ出力の次元が減ります。

16行目のa[:, :, :]は各要素をスライスで指定しており、配列aの内容がそのまま出力されますが、17行目以降のコードでは、要素を直接指定した分だけ出力される配列の次元が減っていることがわかります。

#コード01
import numpy as np
a = np.arange(24).reshape(2, 3, 4)
'''
a =
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
'''

print(a)  #3次元配列を出力
print(a[:, :, :])  #3次元配列を出力
print(a[0, :, :])  #2次元配列を出力
print(a[:, 1, :])  #2次元配列を出力
print(a[:, :, 2])  #2次元配列を出力
print(a[:, 1, 2])  #1次元配列を出力
print(a[0, :, 2])  #1次元配列を出力 
print(a[0, 1, :])  #1次元配列を出力 
print(a[0, 1, 2])  #値(スカラー)を出力

以下をクリックすると、コード01の出力が表示されます。参考資料としてご使用ください。まずは出力配列が何次元になるかだけ分かればよいと思いますので、開かずに次に進んでいただいてもかまいません。

出力01の表示・非表示の切り替え

※ブラウザによっては最初から表示されてしまいます。(Google Chrome推奨)

#出力01
※読みやすいように実際の出力にコメント文を追加しています。
# a =
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
# a[:, :, :] =
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
# a[0, :, :] =
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
# a[:, 1, :] =
[[ 4  5  6  7]
 [16 17 18 19]]
# a[:, :, 2] =
[[ 2  6 10]
 [14 18 22]]
# a[:, 1, 2] =
[ 6 18]
# a[0, :, 2] =
[ 2  6 10]
# a[0, 1, :] =
[4 5 6 7]
# a[0, 1, 2] =
6

なお、少し説明が横道にそれますが、スライス「:」が後ろ側にあるばあいだけスライスを省略できます。一方、a[:, :, 2]をa[, , 2]のようにスライスが前方にある場合は省略することができません。ついでに覚えておきましょう。

#コード02
import numpy as np
a = np.arange(24).reshape(2, 3, 4)

print(a[0, 1, 2])
print(a[0, 1])    #a[0, 1, :]の省略形
print(a[0])       #a[0, :, :]の省略形
print(a)          #a[:, :, :]の省略形

#print(a[, , 2])  #エラー

2.スライスで要素を部分的に指定する場合

NumPy配列ではa[1:3]のようにスライスで要素を部分的に指定することができます。この場合は出力される配列の次元は変化しません。

ここで注意しなければならないのは、a[0:1]のような場合です。a[0:1]はインデックス番号0の要素だけを指定するスライスですが、次元は減りません。a[0]の場合は次元が減りますから、混同しないようにしてください。

コード03の15~19行目は全て出力結果は3次元のままです。

#コード03
import numpy as np
a = np.arange(24).reshape(2, 3, 4)

print(a[:, :, :])  #3次元配列を出力
print(a[:, 0:2, :])  #3次元配列を出力
print(a[:, 0:1, :])  #3次元配列を出力
print(a[0:1, :, 0:1])  #3次元配列を出力
print(a[0:1, 0:1, 0:1])  #3次元配列を出力
出力03の表示・非表示の切り替え

※ブラウザによっては最初から表示されてしまいます。(Google Chrome推奨)

#出力03
# a[:, :, :] =
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
# a[:, 0:2, :] =
[[[ 0  1  2  3]
  [ 4  5  6  7]]

 [[12 13 14 15]
  [16 17 18 19]]]
# a[:, 0:1, :] =
[[[ 0  1  2  3]]

 [[12 13 14 15]]]
# a[0:1, :, 0:1] =
[[[0]
  [4]
  [8]]]
# a[0:1, 0:1, 0:1]) =
[[[0]]]

コード04をみると、要素を整数で直接指定した場合とスライスで指定した場合の違いがよくわかります。5行目のa[0, 0, 0]の出力は0ですが、6行目のa[0:1, 0:1, 0:1]の出力は[[[0]]]です。

#コード04
import numpy as np
a = np.arange(24).reshape(2, 3, 4)

print(a[0, 0, 0]) #1次元配列を出力
print(a[0:1, 0:1, 0:1])  #3次元配列を出力
#出力04
0
[[[0]]]

3.リストで要素を指定する場合

リストで指定する場合は、リストが1つまでなら次元は減らないのですが、2つ目以降は、使った分だけ次元が減ります。

コード05の7~14行目はリストを1カ所しか使用していないので、配列の次元は変化しません。

それに対して、リストを2カ所使った15~22行目の出力は2次元であり、リストを3カ所使った23~26行目の出力は1次元です。

#コード05
import numpy as np
a = np.arange(24).reshape(2, 3, 4)

print('配列a')
print(a)
print('リスト[0, 1]で指定(1カ所)')
print(a[[0, 1], :, :])  #3次元配列を出力
print(a[:, [0, 1], :])  #3次元配列を出力
print(a[:, :, [0, 1]])  #3次元配列を出力
print('リスト[0]で指定(1カ所)')
print(a[[0], :, :])  #3次元配列を出力
print(a[:, [0], :])  #3次元配列を出力
print(a[:, :, [0]])  #3次元配列を出力
print('リスト[0, 1]で指定(2カ所)')
print(a[:, [0, 1], [0, 1]])  #2次元配列を出力
print(a[[0, 1], :, [0, 1]])  #2次元配列を出力
print(a[[0, 1], [0, 1], :])  #2次元配列を出力
print('リスト[0]で指定(2カ所)')
print(a[:, [0], [0]])  #2次元配列を出力
print(a[[0], :, [0]])  #2次元配列を出力
print(a[[0], [0], :])  #2次元配列を出力
print('リストで指定(3カ所)')
print(a[[0, 1], [0, 1], [0,1]])  #1次元配列を出力
print(a[[0], [0], [0]])  #1次元配列を出力
print(a[[0], [0, 1], [0]])  #1次元配列を出力
出力05の表示・非表示の切り替え

※ブラウザによっては最初から表示されてしまいます。(Google Chrome推奨)

#出力05
配列a
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
リスト[0, 1]で指定(1カ所)
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
[[[ 0  1  2  3]
  [ 4  5  6  7]]

 [[12 13 14 15]
  [16 17 18 19]]]
[[[ 0  1]
  [ 4  5]
  [ 8  9]]

 [[12 13]
  [16 17]
  [20 21]]]
リスト[0]で指定(1カ所)
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]]
[[[ 0  1  2  3]]

 [[12 13 14 15]]]
[[[ 0]
  [ 4]
  [ 8]]

 [[12]
  [16]
  [20]]]
リスト[0, 1]で指定(2カ所)
[[ 0  5]
 [12 17]]
[[ 0  4  8]
 [13 17 21]]
[[ 0  1  2  3]
 [16 17 18 19]]
リスト[0]で指定(2カ所)
[[ 0]
 [12]]
[[0 4 8]]
[[0 1 2 3]]
リストで指定(3カ所)
[ 0 17]
[0]
[0 4]

4.リストやスライスを混在させた場合

ここまでの内容がわかれば、リストやスライスを混在させた場合も同じ考え方で理解することができます。

8行目のa[[0], 0, 0:1]について、1番目の[0]はリストが1つしかないので次元は減りません。2番目の0は整数で直接指定しているので次元は減ります。3番目の0:1はスライスなので次元は減りません。したがって、次元が1つ減り2次元配列が出力されます。

9行目のa[[0, 1], 0, 0]について、1番目の[0, 1]はリストが1つしかないので次元は減りません。2番目の0、3番目の0は整数で直接指定しているので次元は減ります。したがって、次元が2つ減り、1次元配列が出力されます。

10行目のa[[0, 1], [0], 0]は、1番目、2番目がリストなので次元は1つ減ります。3番目は整数で直接指定しているので次元は減ります。したがって、次元が2つ減り、1次元配列が出力されます。

#コード06
import numpy as np
a = np.arange(24).reshape(2, 3, 4)

print('配列a')
print(a)
print('リスト[0, 1]で指定(1カ所)')
print(a[[0], 0, 0:1])  #2次元配列
print(a[[0, 1], 0, 0])  #1次元配列を出力
print(a[[0, 1], [0], 0])  #1次元配列を出力
出力06の表示・非表示の切り替え

※ブラウザによっては最初から表示されてしまいます。(Google Chrome推奨)

#出力06
配列a
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
リスト[0, 1]で指定(1カ所)
[[0]]
[ 0 12]
[ 0 12]

私が実際に購入した教材のご紹介

以下、私が実際に購入したPythonの教材をまとめてみました。 Pythonを学習する上で、少しでもお役に立つことができればうれしいです。

Python♪私が購入したPythonの書籍のレビュー
UdemyのPythonの動画講座を書籍を買う感覚で購入してみた

その他

Twitterへのリンクです。SNSもはじめました♪

以下、私が光回線を導入した時の記事一覧です。
 (1) 2020年「光回線は値段で選ぶ」では後悔する ←宅内工事の状況も説明しています。
 (2) NURO光の開通までWiFiルーターを格安レンタルできる
 (3) NURO光の屋外工事の状況をご紹介。その日に開通!
 (4) 光回線開通!実測するとNURO光はやっぱり速かった
 (5) ネット上のNURO光紹介特典は個人情報がもれないの?