どうも!僕です!
つか◯です!
これまではインデックス参照とスライスについて,基礎と多次元配列での参照を行ってきました.
このインデックス参照はブール値,配列を使っても参照ができます.
では,さっそくブールインデックス参照を見ていきましょう.
ブールインデックス参照
ブールインデックス参照は,ブール値で参照します.
ブール値とはなんぞや?というと,「True」or「False」で返されるやつですね.
少し見てみましょう!
まず,適当に人名を入れた配列を作ります.
重複してもOKです.
import numpy as np
names = np.array(["Taro", "Hanako", "Jiro", "Taro", "Jiro", "Hanako", "Hanako", "Kimie"])
print(names)
以下のような配列が生成されます.
['Taro' 'Hanako' 'Jiro' 'Taro' 'Jiro' 'Hanako' 'Hanako' 'Kimie']
では,この配列に「Hanako」が含まれているか,また,それが含まれていた場合どこに格納されているかを確かめましょう!
このとき使うのは「比較演算子」というもので,if文などで使うものですね.
では,見てみましょう.
names == "Hanako"
上記のように表記すると,以下のように「Hanako」がある場所のみ「True」が返されています.
array([False, True, False, False, False, True, True, False])
このように「True」や「False」をブール値(真偽値)といい,これでできた配列を真偽値配列というそうです.
それでは,本題であるブール値を使ったndarrayのインデックス参照を行ってみましょう.
まず,適当な数値を格納した配列を作ります.
このとき,上記の真偽値配列の要素数と参照する配列の軸の要素数を同じにする必要があります.
今回は,真偽値配列の要素数が「8」なので,参照先の配列の行数を「8」にします.
data = np.arange(40).reshape(8, 5)
print(data)
このように生成すると,以下のような数値が各要素に格納されます.
[[ 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 32 33 34]
[35 36 37 38 39]]
では,この配列から真偽値配列の「Hanako」に該当するインデックスのみを取り出してみましょう.
ここで一回予想してください.どの行が取り出されるかを!
予想しましたか?
では,以下のコードを実行しましょう.
data[names == "Hanako"]
このように指定すると,以下のように「Hanako」に該当するところだけ抽出することができます.
array([[ 5, 6, 7, 8, 9],
[25, 26, 27, 28, 29],
[30, 31, 32, 33, 34]])
1, 5, 6番目のインデックスが参照されましたね.
このようにしてブール値でインデックス参照ができます.
これぞまさしく「ブールインデックス参照」ですね.
少し発展的な内容もやっていきましょう.
ブール値×スライス,インデックス
ブールインデックス参照では,スライスも併用できます.
スライスを使うことで,列も指定して参照できます.
以下のコードで何が表示されるか予想してみましょう.
data[names == "Hanako", :2]
予想できましたか?
以下のようになります.
array([[ 5, 6],
[25, 26],
[30, 31]])
「Hanako」の行と0と1番目の列までが抽出されていますね.
スライスだけでなく,列のインデックスも以下のように参照できます.
data[names == "Hanako", 3]
さあ,どこが取り出されるでしょうか?
考えてみましょう!
もうおわかりですね.
array([ 8, 28, 33])
このようにブール値とスライス,インデックスを併用することで細かく参照できます.
逆を参照
これまでは「Hanako」の行だけを参照していましたが,逆に「Hanako以外」を参照することもできます.
これには比較演算子「!=」か,真偽を逆転させる「~」を使ってもいいです.
両方してみましょう!
print("「!=」 = ", names!="Hanako")
print("「!=」 = ", data[names!="Hanako"])
print("「~」 = ", ~(names=="Hanako"))
print("「~」 = ", data[~(names=="Hanako")])
どちらも同じ結果が出力されますので,とりあえず結果を予想してみましょう!
これまでと逆だから...
「!=」 = [ True False True True True False False True]
「!=」 = [[ 0 1 2 3 4]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]
[35 36 37 38 39]]
「~」 = [ True False True True True False False True]
「~」 = [[ 0 1 2 3 4]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]
[35 36 37 38 39]]
こうなりますね!
便宜上,出力は整形してます.
論理演算子の活用
ブールインデックス参照は論理演算子も使用できます.
「and (&) 」や「or (|) 」ですね.
しかも複数条件でできます.
見てみましょう.
今回は「Taro」と「Jiro」を参照したいと思います.
taro_jiro = (names == "Taro") | (names == "Jiro")
print(taro_jiro)
print(data[taro_jiro])
「|」は「or」を意味しています.
真偽値配列では,記号のみしか使えないようなので,「and」の場合は「&」を使います.
皆さん,予想できましたでしょうか?
[ True False True True True False False False]
[[ 0 1 2 3 4]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]]
はい.このようになりますね.
ここまでできれば,もうブールインデックス参照については完璧ですね.
真偽値配列を用いた代入
ここまで要素を取り出す方法を説明してきましたが,ここではそれらを使った数値の代入を行います.
例えば,上記のdataの偶数に0を代入してみましょう.
data[data % 2 == 0] = 0
data
下記のように偶数の要素は0になります.
array([[ 0, 1, 0, 3, 0],
[ 5, 0, 7, 0, 9],
[ 0, 11, 0, 13, 0],
[15, 0, 17, 0, 19],
[ 0, 21, 0, 23, 0],
[25, 0, 27, 0, 29],
[ 0, 31, 0, 33, 0],
[35, 0, 37, 0, 39]])
これを,ブール値を使って値を代入することができます.
先ほどの,「Taro」と「Jiro」の行に,「1000」を代入してみましょう.
data[taro_jiro] = 1000 #taro_jiro = (names == "Taro") | (names == "Jiro")
data
どこが変わるか予想付きましたか?
では見てみましょう!
array([[1000, 1000, 1000, 1000, 1000],
[ 5, 0, 7, 0, 9],
[1000, 1000, 1000, 1000, 1000],
[1000, 1000, 1000, 1000, 1000],
[1000, 1000, 1000, 1000, 1000],
[ 25, 0, 27, 0, 29],
[ 0, 31, 0, 33, 0],
[ 35, 0, 37, 0, 39]])
このように指定したところのみ「1000」にできました.
この操作は,pandasでも使うみたいなので,頭の片隅に入れておきましょう!!
まとめ
今回はブールインデックス参照について説明しました.
これで数値だけでなく,文字列を真偽値にして参照することができますね.
pandasでのDataFrameを扱うときにかなり活用できそうです.
ここについては後程解説します.
今回も,「Pythonによるデータ分析入門」を参考にしています.
次回は,ファンシーインデックス参照について説明します.
これでインデックス参照,スライスの基礎については終わりかなと思ってます.
それでは,一緒に楽しくPythonを学んでいきましょう!!
コメント