このページで解説している内容は、以下の YouTube 動画の解説で見ることができます。

【Python入門】インデックスを指定して配列の要素を取得する

インデックスを使って2次元配列の要素を取り出す

 NumPyの配列では、行列の各要素をインデックスで指定して取得できます。特に2次元配列では、「行番号」と「列番号」の両方を指定する形になります。さらに、ブール配列インデックスを使うことで、「ある条件を満たす」要素だけをまとめて抽出することも可能です。大量のデータがある場合でも、このインデックス操作を駆使すれば、必要なデータだけを効率的に取り出せます。ここでは、インデックス指定による要素取得や、条件に基づく抽出の方法を解説します。

プログラムのダウンロード

 「ダウンロード」から、JupyterLab で実行できるサンプルプログラムがダウンロードできます。ファイルは、ESET Endpoint Securityでウイルスチェックをしておりますが、ダウンロードとプログラムの実行は自己責任でお願いいたします。

1.インデックスを使って2次元配列の要素を取り出す

 NumPyの2次元配列に対して、配列[行番号, 列番号]の形式で要素を取得できます。次のように記述すると、該当箇所の数値を直接参照できます。

1.1.サンプルのCSVファイル(grades1.csv

 以下の例では「grades1.csv」というファイルを用意し、学年やクラスごとに異なる科目の成績データを記録していると想定します。ファイル内容はこのような形式です。

72,88,65
90,94,78
66,70,79
85,82,91
70,60,59
88,90,93
60,72,100
92,89,95
75,67,70
81,88,84

1.2.角括弧を並べる方法とタプルを使う方法

  • 角括弧を並べる方法array[row_index][col_index]
  • タプルを使う方法array[row_index, col_index]
    タプルを囲む丸括弧がありませんが、パッキングの働きによってタプルになります。

 実際にやってみましょう。JupyterLabのセルで以下のコードを動かすと、それぞれの行・列に対応する数値が取得できます。

import numpy as np

# 実行前に、grades.csv をカレントディレクトリに置いておいてください
data = np.loadtxt("grades1.csv", delimiter=",")

# 例: 2行目の中の1列目の要素を取得 (0-based index)
val1 = data[2][1]        # 角括弧を並べる方法
val2 = data[2, 1]        # タプルを使う方法

print("角括弧を並べる方法で取得:", val1)
print("タプルを使う方法で取得    :", val2)

実行結果

角括弧を並べる方法で取得: 70.0
タプルを使う方法で取得    : 70.0
  • 行番号列番号は0から始まる点に注意してください。
  • 例えば「2行目」のインデックスは1になり、「3列目」のインデックスは2になります。

2.行や列全体を取り出す

特定の行や列を丸ごと取得したい場合、スライス構文を使うか、「:」または「...」を利用します。

2.1.行を取得

array[row_index] : 行全体を取得します。たとえば、data[3] は4行目(インデックス3)の行を一括で取り出します。

2.2.列を取得

  • array[:, col_index] : 全行に対してcol_index列を一括取得
  • array[..., col_index]...(Ellipsis)を使って同じ意味を持つ

以下のサンプルでは、2列目(インデックス1)の成績データだけを抜き出します。

import numpy as np

data = np.loadtxt("grades1.csv", delimiter=",")

# 1列目 (インデックス0) 全行 = data[:, 0]
# 2列目 (インデックス1) 全行を取得
second_column = data[:, 1]

print("全行の2列目:", second_column)

実行結果

全行の2列目: [88. 94. 70. 82. 60. 90. 72. 89. 67. 88.]

3.条件に基づいて要素を取り出す(ブール配列インデックス)

 ある列が特定の値以上・以下の行だけをまとめて取得したい場合、NumPyのブール配列インデックスを使うと便利です。これは「配列[式]」という書き方で、式に当てはまるTrueの行を抽出します。

3.1.シンプルな例

例として、3列目(インデックス2)が80点以上の行だけを抜き出す例を示します。

import numpy as np

data = np.loadtxt("grades1.csv", delimiter=",")

# 3列目(インデックス2)が80以上の行だけを取得
extracted = data[data[:, 2] >= 80]
print("3列目が80点以上の行:\n", extracted)

実行結果

3列目が80点以上の行:
 [[ 85.  82.  91.]
 [ 88.  90.  93.]
 [ 60.  72. 100.]
 [ 92.  89.  95.]
 [ 81.  88.  84.]]
  • data[:, 2] >= 80 の部分は、配列中の各要素が「80以上かどうか」の真偽値を返すブール配列。
  • data[ブール配列] は、それがTrueの行だけをまとめて取り出します。

3.2.複数条件を組み合わせる

 NumPyでは、ビット演算子(&, |, ^, ~)を使うことで「AND」や「OR」などの論理演算をブール配列上で行えます。

  • & : AND(両方True)
  • | : OR(どちらかがTrue)
  • ~ : NOT(True→False/False→True)
  • ^ : XOR(片方だけTrue)

 次のサンプルでは、1列目が90以上かつ3列目が85以上の行を抽出します。この場合、両方の条件を満たす行だけが結果に残ります。

import numpy as np

data = np.loadtxt("grades1.csv", delimiter=",")

# 1列目が 90以上 and 3列目が 85以上
extracted_both = data[(data[:, 0] >= 90) & (data[:, 2] >= 85)]
print("1列目が90以上、かつ3列目が85以上:\n", extracted_both)

実行結果

0列目が90以上、かつ2列目が85以上:
 [[92. 89. 95.]]

3.3.any関数やall関数を使う

列ごとに複数条件をまとめて判定したい場合、numpy.any()numpy.all() 関数が利用できます。

  • np.any() : 指定した方向(軸)で1つでもTrueがあればTrue
  • np.all() : 指定した方向(軸)で全てTrueならTrue

たとえば「任意の科目が満点(100点)」の行だけを取得するのであれば、次のように書けます。

import numpy as np

data = np.loadtxt("grades1.csv", delimiter=",")

# array == 100 で、ブール配列を生成
is_hundred = (data == 100)
print(is_hundred)
print()

# 行方向(axis=1)でany()を使って、各行のいずれかが100ならTrue
any_hundred = np.any(is_hundred, axis=1)
print(any_hundred)
print()

# これをブール配列インデックスとして使う
extracted_hundred = data[any_hundred]
print("どれかの列が100点の行:\n", extracted_hundred)

実行結果

[[False False False]
 [False False False]
 [False False False]
 [False False False]
 [False False False]
 [False False False]
 [False False  True]
 [False False False]
 [False False False]
 [False False False]]

[False False False False False False  True False False False]

どれかの列が100点の行:
 [[ 60.  72. 100.]]

まとめ

 NumPyの配列では、行と列の「インデックス」を指定することで、必要な要素だけを的確に取り出せます。2次元以上の場合は array[row, col] の形式を使うと読みやすく、ブール配列インデックスを用いれば条件に合う行だけを一括抽出可能です。大量データを扱う機械学習やデータ解析の現場では、これらの操作をマスターしておくと、前処理やフィルタリングが格段に楽になります。次のステップとして、より複雑なスライスや配列の変形(reshapeなど)を学ぶことで、大規模データセットでも柔軟な処理が可能になるでしょう。