はじめに
今回はfilter
関数を複数の列に一気に適応するための関数であるfilter_at
関数、filter_all
関数、filter_if
関数の使い方や使い分けを紹介したいと思います。これらの関数はdplyr
パッケージに含まれる関数です。 これらを使うと複数の列に対して同一条件でフィルタリングする場合(列Aと列Bが5以下になるようフィルタリングする場合など)に無駄に長いコードを書かなくて良くなりコードの可読性が上がります。
使い方
今回紹介する関数はfilter
関数の拡張版のような関数です。ポイントはフィルターを適応する列をどのように選ぶのかです。
今回紹介する3つの関数の特徴や使い分け方は次の通りです。
関数 | 特徴 | 使いどころ |
---|---|---|
filter_all |
全ての列にフィルターを適応 | 列の指定が面倒な時(あまり推奨されない) |
filter_at |
列名に応じて複数の列にフィルターを適応 | 位置や名前で列が指定できる時 |
filter_if |
列の中身に応じて複数の列にフィルターを適応 | 列の中身で列を指定できる時 |
図にするとこんな感じのイメージになります。
またこれらの関数では基本的にヘルパー関数としてall_vars()
やany_vars()
関数を使ってフィルタリング条件を指定します。
all_vars()
とany_vars()
の特徴や使い分けは以下の通りです。
関数 | 特徴 | 使いどころ |
---|---|---|
all_vars |
全ての指定された列でフィルタリング条件を満たすものだけ抽出 | 厳しくフィルタリングをかけたい場合 |
any_vars |
指定された列のいずれかでフィルタリング条件を満たすものは抽出 | ゆるくフィルタリングをかけたい場合 |
この関数の特徴を図にするとこんな感じのイメージになります。
また今回紹介する関数は複数の列を指定することが前提となっているので、フィルタリング条件の条件式の書き方が変わり、列名を代名詞的な方法として.
で表現するという特徴もあります。
これらのことは説明するとややこしいので次の章から具体例をたくさん挙げて紹介します。
具体例
今回はiris
データを用いて具体的なコードを紹介していきたいと思います。
filter_all
filter_all
関数はfilter
関数を全ての列に適応する関数です。全ての列に条件を適応できる場合にはこれを使うことができます。(文字列型になっている列がある場合に数値フィルターをかける場合などは型の整合性がとれずエラーとなります。)
今回はfilter_all
関数についてall_vars()
を使うパターンと any_vars()
を使うパターンの両方をやってみたいと思います。
まずはiris
データから全ての測定値が2.5以上となっているデータだけ抽出する例を紹介します。
library(dplyr) data = iris[, 1:4] # 種名以外の測定値だけを取り出す filter_all(data, all_vars(. >= 2.5))
表示される結果はこんな感じになります(クリックで表示)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width |
---|---|---|---|
6.3 | 3.3 | 6 | 2.5 |
7.2 | 3.6 | 6.1 | 2.5 |
6.7 | 3.3 | 5.7 | 2.5 |
見てわかるようにすべての列の値が2.5以上になっています。
ちなみにこの関数のイメージは以下の通りです。
次にiris
データから全ての列の中からいずれかの測定値が2.5以上となっているデータだけ抽出する例を紹介します。
library(dplyr) data = iris[, 1:4] # 種名以外の測定値だけを取り出す filter_all(data, any_vars(. >= 2.5))
表示される結果の頭10行はこんな感じになります(クリックで表示)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width |
---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 |
4.9 | 3 | 1.4 | 0.2 |
4.7 | 3.2 | 1.3 | 0.2 |
4.6 | 3.1 | 1.5 | 0.2 |
5 | 3.6 | 1.4 | 0.2 |
5.4 | 3.9 | 1.7 | 0.4 |
4.6 | 3.4 | 1.4 | 0.3 |
5 | 3.4 | 1.5 | 0.2 |
4.4 | 2.9 | 1.4 | 0.2 |
こちらでは Sepal.Length や Sepal.Width の値は2.5以上になっていますが、 Petal.Width や Petal.Length の値が2.5以下となっています
filter_at
filter_at
関数はfilter
関数を列名などで指定した複数の列に適応する関数です。適応したくない列がある場合で列の位置や列名で指定することができそうな場合はこれを使うと良いです。
まずはiris
データの1列目と2列目の値がどちらも4より大きな値になる行を抽出するコードを紹介します。
library(dplyr) data = iris filter_at(data, .vars = c(1, 2), .vars_predicate = all_vars(. > 4)) # 列の位置で指定する場合 # 下のコードでも同様のフィルターができます。 # 列名で指定する場合 # filter_at(data, .vars = c("Sepal.Length", "Sepal.Width"), .vars_predicate = all_vars(. > 4)) # selectのヘルパー関数を使う場合 # filter_at(data, .vars = vars(matches("Sepal")), .vars_predicate = all_vars(. > 4))
表示される結果はこんな感じになります(クリックで表示)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width |
---|---|---|---|
5.7 | 4.4 | 1.5 | 0.4 |
5.2 | 4.1 | 1.5 | 0.1 |
5.5 | 4.2 | 1.4 | 0.2 |
次にiris
データの1列目と2列目の値のうちどちらかが7.5より大きな値になる行を抽出するコードを紹介します。
library(dplyr) data = iris filter_at(data, .vars = c(1, 2), .vars_predicate = any_vars(. > 7.5))
表示される結果はこんな感じになります(クリックで表示)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width |
---|---|---|---|
7.6 | 3 | 6.6 | 2.1 |
7.7 | 3.8 | 6.7 | 2.2 |
7.7 | 2.6 | 6.9 | 2.3 |
7.7 | 2.8 | 6.7 | 2 |
7.9 | 3.8 | 6.4 | 2 |
7.7 | 3 | 6.1 | 2.3 |
こちらでは Sepal.Length 列は条件を満たしていますが、Sepal.Width 列は条件を満たしていません。
filter_if
filter_if
関数はfilter
関数を列の中身に応じて複数の列に適応する関数です。適応したくない列がある場合に列の内容でフィルターをかける列が指定できそうなときはこの関数を使います。
今回はiris
データから列の中身が数字型になっている全ての列の値が2.5以上になっている行を抽出するコードを紹介します。
library(dplyr) data = iris filter_if(data, .predicate = is.numeric, .vars_predicate = all_vars(. >= 2.5))
表示される結果はこんな感じになります(クリックで表示)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
---|---|---|---|---|
6.3 | 3.3 | 6 | 2.5 | virginica |
7.2 | 3.6 | 6.1 | 2.5 | virginica |
6.7 | 3.3 | 5.7 | 2.5 | virginica |
次に列の中身が数字型になっている列のうちどれかの値が2.5以上になっている行を抽出するコードを紹介します。
library(dplyr) data = iris filter_if(data, .predicate = is.numeric, .vars_predicate = any_vars(. >= 2.5))
表示される結果の頭10行はこんな感じになります(クリックで表示)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa |
4.9 | 3 | 1.4 | 0.2 | setosa |
4.7 | 3.2 | 1.3 | 0.2 | setosa |
4.6 | 3.1 | 1.5 | 0.2 | setosa |
5 | 3.6 | 1.4 | 0.2 | setosa |
5.4 | 3.9 | 1.7 | 0.4 | setosa |
4.6 | 3.4 | 1.4 | 0.3 | setosa |
5 | 3.4 | 1.5 | 0.2 | setosa |
4.4 | 2.9 | 1.4 | 0.2 | setosa |
4.9 | 3.1 | 1.5 | 0.1 | setosa |
最後に列の中身がファクター型になっている全ての列で値が versicolorになっている行を抽出するコードを紹介します。
(具体例を紹介するためにこのコードを書いていますが適応する列が1列しかないため普通のfilter
関数を使った方がスマートです。)
library(dplyr) data = iris filter_if(data, .predicate = is.factor, .vars_predicate = all_vars(. == "versicolor")) # 今回の場合は普通のfilter関数を使った方がスマート(対象列が1列しかないため) # filter(data, Species == "versicolor")
表示される結果の頭10行はこんな感じになります(クリックで表示)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
---|---|---|---|---|
7 | 3.2 | 4.7 | 1.4 | versicolor |
6.4 | 3.2 | 4.5 | 1.5 | versicolor |
6.9 | 3.1 | 4.9 | 1.5 | versicolor |
5.5 | 2.3 | 4 | 1.3 | versicolor |
6.5 | 2.8 | 4.6 | 1.5 | versicolor |
5.7 | 2.8 | 4.5 | 1.3 | versicolor |
6.3 | 3.3 | 4.7 | 1.6 | versicolor |
4.9 | 2.4 | 3.3 | 1 | versicolor |
6.6 | 2.9 | 4.6 | 1.3 | versicolor |
5.2 | 2.7 | 3.9 | 1.4 | versicolor |
まとめ
今回はfilter
関数の発展版としてfilter_all
、filter_at
、filter_if
関数を紹介しました。覚えておくとコードを簡単にできるので頭に入れておくと良いかもしれません。