こんにちは,shun(@datasciencemore)です!!
前回,dplyrの最重要関数であるfilter, select, mutateについて,学習しました.
次の段階はこれらをより深く学んでいきましょう.
今回は,filterを重点的にやっていきましょう.
まず,filterの復習です.
filterは,条件を指定してあげて,その条件を満たした行を抽出するときに使用するんでしたね.
この一見シンプルに見えるfilterですが,実はいろいろな機能があるので,一つ一つ見ていきましょう.
0.filterの内部処理
filterは,実は
① 条件を判定し,行ごとに論理値ベクトル(TRUE,FALSE)を作成する.
② ①の論理値ベクトルをデータフレームに記録する.
③ ②でTRUEであった行のみを抽出する.
ということを順番に内部でしています.

大丈夫,これも例をみればイメージがつかめるよ!
例えば,次のようなデータフレーム(dfとする.)を考えます.
ちなみにこのデータフレームは,とある会社の従業員の性別(gender)と身長(height)を表すデータです.
1 2 3 4 5 6 |
df = tibble( No = (1:7) %>% factor(), gender = c("M", "F", "F", "M", "F", "M", "M"), height = c(165, 150, 170, 175, 165, 195, 180) ) |
1 2 3 4 5 6 7 8 9 10 |
# A tibble: 7 x 3 No gender height <fct> <chr> <dbl> 1 1 M 165 2 2 F 150 3 3 F 170 4 4 M 175 5 5 F 165 6 6 M 195 7 7 M 180 |
このデータフレームからgender = Fの行を抽出してみましょう.
1 2 3 4 5 6 7 8 9 |
df %>% filter(gender == "F") # A tibble: 3 x 3 No gender height <fct> <chr> <dbl> 1 2 F 150 2 3 F 170 3 5 F 165 |
はい,無事に指定した条件で抽出できましたね.
これは,内部的に以下のような流れで処理されています.
① gender == "F"を判定し,行ごとに論理値ベクトル(TRUE,FALSE)を作成する.
② ①の論理値ベクトルをdfに記録する.
③ ②でTRUEとなった行のみを抽出する.

要するに,
条件を判定して,論理値ベクトルを作成し,その論理値ベクトルをもとに抽出される行が決定される!!
ということです.
この仕組みによって,実はfilterの()内に直接,論理値ベクトルを入れても動作します.
1 2 3 4 5 6 7 8 9 |
df %>% filter( c(FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE) ) # A tibble: 3 x 3 No gender height <fct> <chr> <dbl> 1 2 F 150 2 3 F 170 3 5 F 165 |
上の結果と全く同じ結果になりました.
gender == "F"
の判定結果がc(FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE)
なので当然ですね.
この考え方はめっちゃ大事なので,イメージできるようになってください!!
それでは,次章以降は,この考え方を応用してより複雑な条件を考えてみましょう.
以降のデータはおなじみのdiamonodsを使用します.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# A tibble: 53,940 x 10 carat cut color clarity depth table price x y z <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31 3 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31 4 0.290 Premium I VS2 62.4 58 334 4.2 4.23 2.63 5 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75 6 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48 7 0.24 Very Good I VVS1 62.3 57 336 3.95 3.98 2.47 8 0.26 Very Good H SI1 61.9 55 337 4.07 4.11 2.53 9 0.22 Fair E VS2 65.1 61 337 3.87 3.78 2.49 10 0.23 Very Good H VS1 59.4 61 338 4 4.05 2.39 # … with 53,930 more rows |
1.数値フィルタ
まずは数値フィルタでいろいろなフィルタを試してみましょう.
数値フィルタとは,データ型がintかdblの列について,条件を指定することとします.
1 2 3 4 5 6 7 8 |
diamonds %>% filter(price == 337) # A tibble: 2 x 10 carat cut color clarity depth table price x y z <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> 1 0.26 Very Good H SI1 61.9 55 337 4.07 4.11 2.53 2 0.22 Fair E VS2 65.1 61 337 3.87 3.78 2.49 |
1 2 3 |
#price列が337の行をフィルタリング diamonds %>% filter(price == 337) |
1 2 3 4 5 |
# A tibble: 2 x 10 carat cut color clarity depth table price x y z <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> 1 0.26 Very Good H SI1 61.9 55 337 4.07 4.11 2.53 2 0.22 Fair E VS2 65.1 61 337 3.87 3.78 2.49 |
1 2 3 |
#depth列が62以上の行をフィルタリング diamonds %>% filter(depth >= 62) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# A tibble: 24,669 x 10 carat cut color clarity depth table price x y z <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> 1 0.290 Premium I VS2 62.4 58 334 4.2 4.23 2.63 2 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75 3 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48 4 0.24 Very Good I VVS1 62.3 57 336 3.95 3.98 2.47 5 0.22 Fair E VS2 65.1 61 337 3.87 3.78 2.49 6 0.3 Good J SI1 64 55 339 4.25 4.28 2.73 7 0.23 Ideal J VS1 62.8 56 340 3.93 3.9 2.46 8 0.31 Ideal J SI2 62.2 54 344 4.35 4.37 2.71 9 0.3 Ideal I SI2 62 54 348 4.31 4.34 2.68 10 0.3 Good J SI1 63.4 54 351 4.23 4.29 2.7 # … with 24,659 more rows |
1 2 3 |
#carat列が0.23~0.27の行をフィルタリング diamonds %>% filter(between(carat, 0.23, 0.27)) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# A tibble: 1,245 x 10 carat cut color clarity depth table price x y z <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43 2 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31 3 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48 4 0.24 Very Good I VVS1 62.3 57 336 3.95 3.98 2.47 5 0.26 Very Good H SI1 61.9 55 337 4.07 4.11 2.53 6 0.23 Very Good H VS1 59.4 61 338 4 4.05 2.39 7 0.23 Ideal J VS1 62.8 56 340 3.93 3.9 2.46 8 0.23 Very Good E VS2 63.8 55 352 3.85 3.92 2.48 9 0.23 Very Good H VS1 61 57 353 3.94 3.96 2.41 10 0.23 Very Good G VVS2 60.4 58 354 3.97 4.01 2.41 # … with 1,235 more rows |
さりげなくbetweenを使用しましたが,これは,以下と同じことです.
1 2 |
diamonds %>% filter(carat >= 0.23, carat <= 0.27) |
betweenを使うと簡潔に書けるので,慣れてくださいね.
※ただし,指定した両端の値(今回の例だと0.23と0.27)も含むので,注意してください.
2.文字列フィルタ
次に文字列フィルタです.
文字列フィルタとは,データ型がchrかfactorの列について,条件を指定することとします.
1 2 3 |
#cut列がIdealの行をフィルタリング diamonds %>% filter(cut == "Ideal") |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# A tibble: 21,551 x 10 carat cut color clarity depth table price x y z <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43 2 0.23 Ideal J VS1 62.8 56 340 3.93 3.9 2.46 3 0.31 Ideal J SI2 62.2 54 344 4.35 4.37 2.71 4 0.3 Ideal I SI2 62 54 348 4.31 4.34 2.68 5 0.33 Ideal I SI2 61.8 55 403 4.49 4.51 2.78 6 0.33 Ideal I SI2 61.2 56 403 4.49 4.5 2.75 7 0.33 Ideal J SI1 61.1 56 403 4.49 4.55 2.76 8 0.23 Ideal G VS1 61.9 54 404 3.93 3.95 2.44 9 0.32 Ideal I SI1 60.9 55 404 4.45 4.48 2.72 10 0.3 Ideal I SI2 61 59 405 4.3 4.33 2.63 # … with 21,541 more rows |
1 2 3 |
#color列がE以外の行をフィルタリング diamonds %>% filter(color != "E") |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# A tibble: 44,143 x 10 carat cut color clarity depth table price x y z <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> 1 0.290 Premium I VS2 62.4 58 334 4.2 4.23 2.63 2 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75 3 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48 4 0.24 Very Good I VVS1 62.3 57 336 3.95 3.98 2.47 5 0.26 Very Good H SI1 61.9 55 337 4.07 4.11 2.53 6 0.23 Very Good H VS1 59.4 61 338 4 4.05 2.39 7 0.3 Good J SI1 64 55 339 4.25 4.28 2.73 8 0.23 Ideal J VS1 62.8 56 340 3.93 3.9 2.46 9 0.22 Premium F SI1 60.4 61 342 3.88 3.84 2.33 10 0.31 Ideal J SI2 62.2 54 344 4.35 4.37 2.71 # … with 44,133 more rows |
1 2 3 |
#color列がIまたはJの行をフィルタリング diamonds %>% filter(color %in% c("I", "J")) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# A tibble: 8,230 x 10 carat cut color clarity depth table price x y z <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> 1 0.290 Premium I VS2 62.4 58 334 4.2 4.23 2.63 2 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75 3 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48 4 0.24 Very Good I VVS1 62.3 57 336 3.95 3.98 2.47 5 0.3 Good J SI1 64 55 339 4.25 4.28 2.73 6 0.23 Ideal J VS1 62.8 56 340 3.93 3.9 2.46 7 0.31 Ideal J SI2 62.2 54 344 4.35 4.37 2.71 8 0.3 Ideal I SI2 62 54 348 4.31 4.34 2.68 9 0.3 Good J SI1 63.4 54 351 4.23 4.29 2.7 10 0.3 Good J SI1 63.8 56 351 4.23 4.26 2.71 # … with 8,220 more rows |
ベクトル1 %in% ベクトル2でベクトル1の各要素に対して,ベクトル2が含まれるか否かを判定した論理値ベクトルを返します.
イメージは以下のとおり
3.NAフィルタ
データフレームに常に値が入っているとは限りません.
欠損値としてNAがある場合も多々あります.
そういうときのフィルタリングについて紹介します.
1 2 3 |
#cut列がNAの行をフィルタリング diamonds %>% filter(is.na(cut)) |
1 2 3 |
# A tibble: 0 x 10 # … with 10 variables: carat <dbl>, cut <ord>, color <ord>, clarity <ord>, depth <dbl>, table <dbl>, price <int>, x <dbl>, # y <dbl>, z <dbl> |
NAがないから1行も抽出されませんでしたね笑
該当する行がない場合は,こんな感じで出力されます.
初めて見るとビビりますが,問題ないですよ笑
念のため,NAがあるデータフレームで確かめてみましょう.
1 2 3 4 5 |
# NAがあるデータフレームを定義 df = tibble( col = c(1, 3, NA, 5, 4, 8, NA, 9, NA) ) |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
> df # A tibble: 9 x 1 col <dbl> 1 1 2 3 3 NA 4 5 5 4 6 8 7 NA 8 9 9 NA |
1 2 3 |
# NAがある行を抽出 df %>% filter( is.na(col)) |
1 2 3 4 5 6 |
# A tibble: 3 x 1 col <dbl> 1 NA 2 NA 3 NA |
はい,しっかりとNAだけ抽出できました!
4.複合フィルタ
複合フィルタってのは,そんなに難しいことじゃありません.
今までの1~3では,指定した条件から作成された論理値ベクトルでTRUEの行が抽出されることを学びました.
実は,この指定した条件から作成された論理値ベクトルを論理演算(AND,OR,XOR,NOT)で組み合わせることができます.
これも言葉だけだと何言ってるのかよくわからないので,例によって図で説明しますね.

データフレームにfilterを適用すると論理値ベクトルが得られるのでした.
ここで得られる論理値ベクトルは指定した条件ごとに違いますよね.
例えばdiamondsで説明すると
条件1:depth列が62以上の行をフィルタリング
条件2:color列がHの行をフィルタリング
とすると,条件1と条件2で,それぞれに対応する論理値ベクトルが得られます.
これらの論理値ベクトルに論理演算を適用することができます.
例えば,depth列が62以上でcolor列がHの行をフィルタリングしたいなぁと思ったら
条件1で得られた論理値ベクトルと条件2で得られた論理値ベクトルにAND演算をすればOKです.
もちろんAND演算だけではなく,残りのOR,XOR,NOTも使用できます.
以下,具体例を挙げます.
AND
1 2 3 4 5 6 7 |
#depth列が62以上かつcolor列がHの行をフィルタリング(AND) diamonds %>% filter(depth >= 62 & color == "H") #ANDは,以下でもOK diamonds %>% filter(depth >= 62 , color == "H") |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# A tibble: 4,045 x 10 carat cut color clarity depth table price x y z <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> 1 0.31 Good H SI1 64 54 402 4.29 4.31 2.75 2 0.32 Good H SI2 63.1 56 403 4.34 4.37 2.75 3 0.32 Good H SI2 63.8 56 403 4.36 4.38 2.79 4 0.3 Very Good H SI1 63.1 56 554 4.29 4.27 2.7 5 0.3 Premium H SI1 62.9 59 554 4.28 4.24 2.68 6 0.3 Premium H SI1 62.5 57 554 4.29 4.25 2.67 7 0.3 Good H SI1 63.7 57 554 4.28 4.26 2.72 8 0.91 Fair H SI2 64.4 57 2763 6.11 6.09 3.93 9 0.91 Fair H SI2 65.7 60 2763 6.03 5.99 3.95 10 0.77 Ideal H VS2 62 56 2763 5.89 5.86 3.64 # … with 4,035 more rows |
OR
1 2 3 |
#depth列が62以上またはcolor列がHの行をフィルタリング(OR) diamonds %>% filter(depth >= 62 | color == "H") |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# A tibble: 28,928 x 10 carat cut color clarity depth table price x y z <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> 1 0.290 Premium I VS2 62.4 58 334 4.2 4.23 2.63 2 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75 3 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48 4 0.24 Very Good I VVS1 62.3 57 336 3.95 3.98 2.47 5 0.26 Very Good H SI1 61.9 55 337 4.07 4.11 2.53 6 0.22 Fair E VS2 65.1 61 337 3.87 3.78 2.49 7 0.23 Very Good H VS1 59.4 61 338 4 4.05 2.39 8 0.3 Good J SI1 64 55 339 4.25 4.28 2.73 9 0.23 Ideal J VS1 62.8 56 340 3.93 3.9 2.46 10 0.31 Ideal J SI2 62.2 54 344 4.35 4.37 2.71 # … with 28,918 more rows |
XOR
1 2 3 |
#depth列が62以上,color列がHの排他的論理和の行をフィルタリング(XOR) diamonds %>% filter(xor(depth >= 62, color == "H")) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# A tibble: 24,883 x 10 carat cut color clarity depth table price x y z <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> 1 0.290 Premium I VS2 62.4 58 334 4.2 4.23 2.63 2 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75 3 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48 4 0.24 Very Good I VVS1 62.3 57 336 3.95 3.98 2.47 5 0.26 Very Good H SI1 61.9 55 337 4.07 4.11 2.53 6 0.22 Fair E VS2 65.1 61 337 3.87 3.78 2.49 7 0.23 Very Good H VS1 59.4 61 338 4 4.05 2.39 8 0.3 Good J SI1 64 55 339 4.25 4.28 2.73 9 0.23 Ideal J VS1 62.8 56 340 3.93 3.9 2.46 10 0.31 Ideal J SI2 62.2 54 344 4.35 4.37 2.71 # … with 24,873 more rows |
NOT
1 2 3 |
#depth列が62以上かつcolor列がHではない行をフィルタリング(NOT) diamonds %>% filter(!(depth >= 62 & color == "H")) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# A tibble: 49,895 x 10 carat cut color clarity depth table price x y z <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31 3 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31 4 0.290 Premium I VS2 62.4 58 334 4.2 4.23 2.63 5 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75 6 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48 7 0.24 Very Good I VVS1 62.3 57 336 3.95 3.98 2.47 8 0.26 Very Good H SI1 61.9 55 337 4.07 4.11 2.53 9 0.22 Fair E VS2 65.1 61 337 3.87 3.78 2.49 10 0.23 Very Good H VS1 59.4 61 338 4 4.05 2.39 # … with 49,885 more rows |
複合条件を使うことでいろいろなパターンのデータフレームを抽出することができます.
まとめ
今回はfilterの使い方についてまとめました.
filterは内部的に論理値ベクトルによって抽出する行を選択しています.
また,filterの具体例についてまとめると,以下のようになります.
- 数値フィルタ
- 文字列フィルタ
- NAフィルタ
- 複合フィルタ
このうち,4の複合フィルタは,1~3の条件の論理値ベクトルを論理演算で組み合わせることによって新たな論理値ベクトルを作成するのでした.
これらを屈指すればいろいろな条件を作成できますよ.
ぜひ実際に手を動かして試してみてくださいね!!
それじゃ,お疲れ様でした!!