6
6

More than 3 years have passed since last update.

NumPy配列の列を抽出する方法いろいろ

Last updated at Posted at 2020-07-02

2次元配列の列を取り出す方法のいろいろ.

import

import numpy as np

配列の生成

まずは適当に5x4の配列を生成

a = np.arange(5*4).reshape([5, 4])
print(a)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]
#  [12 13 14 15]
#  [16 17 18 19]]

特定の1列を抽出する

# 2列目のみ
b = a[:, 2]
print(b)
# [ 2 6 10 14 18]

a[row, column]とすると, rowの部分で行の指定, columnの部分で列の指定を行う.
今回は列を取り出したいので, rowの部分は常に:とする. :のみ記述することで, 行に関しては特に指定しないという意味になる. つまりa[:, 2]は, 「すべての行から, インデックスが2の要素だけください」ということになる.

連続する複数の列を抽出する

1, 2列目や0~2列目など, 連続する複数の列を取り出す.

# 1, 2列目
b = a[:, 1:3]
print(b)
# [[ 1  2]
#  [ 5  6]
#  [ 9 10]
#  [13 14]
#  [17 18]]

1:3は1以上3未満を意味するため, 1~2列目が取り出せる.
1::3のように指定すれば, 1列目以上や3列目未満の列がすべて取得できる.

# 1列目~
b = a[:, 1:]
print(b)
# [[ 1  2  3]
#  [ 5  6  7]
#  [ 9 10 11]
#  [13 14 15]
#  [17 18 19]]

# 0~2列目
b = a[:, :3]
print(b)
# [[ 0  1  2]
#  [ 4  5  6]
#  [ 8  9 10]
#  [12 13 14]
#  [16 17 18]]

偶数列, 奇数列など

# 4x8の配列を生成
a = np.arange(4*8).reshape([4, 8])
# [[ 0  1  2  3  4  5  6  7]
#  [ 8  9 10 11 12 13 14 15]
#  [16 17 18 19 20 21 22 23]
#  [24 25 26 27 28 29 30 31]]

# 偶数列
b = a[:, ::2]
print(b)
# [[ 0  2  4  6]
#  [ 8 10 12 14]
#  [16 18 20 22]
#  [24 26 28 30]]

# 奇数列
b = a[:, 1::2]
print(b)
# [[ 1  3  5  7]
#  [ 9 11 13 15]
#  [17 19 21 23]
#  [25 27 29 31]]

このように, 基本的にリストの操作方法に則っているため, 倍数や逆順での取得も可能.

# 後ろから3の倍数の列
b = a[:, ::-3]
print(b)
# [[ 7  4  1]
#  [15 12  9]
#  [23 20 17]
#  [31 28 25]]

# 1列目以上7列目未満の一列飛ばし
b = a[:, 1:7:2]
print(b)
# [[ 1  3  5]
#  [ 9 11 13]
#  [17 19 21]
#  [25 27 29]]

不規則に複数の列を抽出する

個人的にはここからが本題.
1, 5, 6列などのように, 不規則に列を取り出したいときがある.
ひと手間増えるが, 列の数と同じ長さのフィルターを用意することで実現できる.

# インデックス1, 5, 6の値がTrue, それ以外がFalseの長さ8のリスト
f = [False, True, False, False, False, True, True, False]

b = a[:, f]
print(b)
# [[ 1  5  6]
#  [ 9 13 14]
#  [17 21 22]
#  [25 29 30]]

# boolean型の1x8の零行列を生成して, 欲しい列のインデックスの値だけTrueに変えるパターン
f = np.zeros(8, dtype=bool)
columns = [1, 5, 6]
f[columns] = True

b = a[:, f]
print(b)
# [[ 1  5  6]
#  [ 9 13 14]
#  [17 21 22]
#  [25 29 30]]

# 指定した列以外を取得したい場合はonesですべてTrueの配列を生成し, いらない列だけFalseに変える
f = np.ones(8, dtype=bool)
columns = [1, 5, 6]
f[columns] = False

b = a[:, f]
print(b)
# [[ 0  2  3  4  7]
#  [ 8 10 11 12 15]
#  [16 18 19 20 23]
#  [24 26 27 28 31]]

numpyで扱う配列は列の数が多い場合がほとんどだと思うので, 二つ目の方法がメインになってくると思う.
例ではnp.zerosを使用しているが, 状況によってはnp.onesで要素がすべてTrueの配列を作ってから, いらない列だけFalseに変える方が楽かもしれない.

※ 2020/07/04に追記
np.zerosを使う方法よりも簡単な方法をコメントで教えていただいたので, 下に示す.

# 4x8の配列を生成
a = np.arange(4*8).reshape([4, 8])
# [[ 0  1  2  3  4  5  6  7]
#  [ 8  9 10 11 12 13 14 15]
#  [16 17 18 19 20 21 22 23]
#  [24 25 26 27 28 29 30 31]]

# 1, 5, 6列を取り出す
b = a[:, [1, 5, 6]]
print(b)
# [[ 1  5  6]
#  [ 9 13 14]
#  [17 21 22]
#  [25 29 30]]

おわりに

あまり話を広げすぎてもわかりづらいと思い, 今回は列のみに絞って解説したが, 列同様に行も指定することで特定の行の特定の列を取り出すこともできる. 3次元以上の場合もこれらの方法を応用することで, 欲しい要素を抽出できる.

一番最後に解説した零行列を作って列を取り出す方法は, 自分としては結構綺麗にできたと思うけど、他にもっと楽な方法がありそうな気もする.

追記

複数の列を取り出す, よりスマートな方法を@nkayさんにコメントで教えていただいたので, 書き加えた. (July 4, 2020)

6
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6