Vectorsの概念で見たように、ベクトルは条件式の中で使うことができ、真偽値のベクトルが得られます。
これはさらに、all()やany()といった関数でも使うことができます。
v <- c(4, 7, 10)
v >= 6
#> [1] FALSE TRUE TRUE
all(v > 6)
#> [1] FALSE # not all elements match this condition
any(v > 6)
#> [1] TRUE # at least one element matches
このテクニックは、ここで見たものよりはるかに強力です。
ベクトルから特定の要素を取り出すには、インデックス番号か、インデックスのベクトルを使います。
v <- 5:10
v
#> [1] 5 6 7 8 9 10
v[3]
#> [1] 7
v[c(2, 4)]
#> [1] 6 8
別の方法として、論理値のベクトルを使って元のベクトルを絞り込み、TRUEに対応する要素の部分集合を返すこともできます。
v <- 1:3
bools <- c(FALSE, TRUE, TRUE)
v[bools]
#> [1] 2 3
そこから、条件式で真偽値のベクトルを生成するまで、あと一歩です。
bools <- v >= 2
bools
#> [1] FALSE TRUE TRUE
v[bools]
#> [1] 2 3
# simpler form
v[v >= 2]
#> [1] 2 3
これらの条件式は、複数のベクトルや関数を組み合わせて、いくらでも複雑にできます。
v <- 1:10
w <- 10:1
# pairwise comparison
v > w
#> [1] FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE
# shorter form
v[v > w]
#> [1] 6 7 8 9 10
この概念を「Vector Filtering」と名付けました。できるだけ多くのプログラマーに意味が通じることを願ってのことです。
Rコミュニティの中では、「Subsetting」という言葉のほうがよく使われるでしょう。
話を簡単にするため、上の例ではどれも同じ長さのベクトルを比較しました。 長さが合わなかったらどうなるのでしょうか?
その答えは、意図して使えば強力ですが、予期していないと混乱を招くものです。
例を見てみましょう。
v <- 1:6
cond <- c(TRUE, FALSE)
v[cond]
#> [1] 1 3 5
何が起きたのでしょうか? 長さ6のベクトルを、長さ2の真偽値でインデックス指定しましたが、結果は長さ3のベクトルになりました。
式の中で使うにはベクトルが「短すぎる」とき、Rは目的の長さに達するまでそのベクトルを繰り返します。これが「リサイクル」です。
これにより、c(TRUE, FALSE)というベクトルはc(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE)になり、v[cond]はvのうちTRUEに対応する値、この場合は奇数を返しました。
では、次の例では何が起きているのでしょうか?
v <- 1:3
0.5 * v
#> [1] 0.5 1.0 1.5
2 + v
#> [1] 3 4 5
一見するとスカラー倍と、(少し変わった)スカラー加算のように見えますが、Rにスカラーはありません。
代わりに、数値がリサイクルされてvと同じ長さのベクトルになり、c(0.5, 0.5, 0.5)やc(2, 2, 2)を使って要素ごとに演算が適用されます。
リサイクルはとてもとても便利ですが、本当にそれが意図した動作か確認しましょう。
ベクトルの長さが少しでも食い違うと(たとえば99と100)、混乱を招くバグの原因になります。
リサイクルは、どちらかのベクトルの長さが1のときだけ使うことを勧める人もいます。
which()関数は真偽値の引数を取り、TRUEになるインデックスのベクトルを返します。
v
#> [1] 2 7 9
v[v > 5] # returns values
#> [1] 7 9
which(v > 5) # returns indices
#> [1] 2 3
ここまでの節では、ある条件に合う要素を見つける方法を扱ってきました。
特定の要素がベクトルに含まれているかどうかだけを知りたいときは、%in%演算子を使います。
3 %in% 1:5
#> [1] TRUE
7 %in% 1:5
#> [1] FALSE
これは次のコードと機能的には同じですが、ずっと便利です。
length(v[v == 3]) > 0
#> [1] TRUE
%notin%演算子というものもあり、%in%の論理notを返します。