R言語でデータフレームから条件を満たす行を取得する方法について解説します。このような方法はいくつかあり、R言語に標準で搭載されている機能を使用した方法もありますが、ここではtidyverseパッケージに含まれているdplyrパッケージのfilter()を使用した方法についてお伝えします。filter()を使用する利点は、パイプ演算子と親和性が高くR言語に標準で搭載されている機能を使用する方法よりも可読性が高いコードが書けることが挙げられます。

filter()の概要

filter()は、条件に一致する行を保持する関数です。これは、データフレームをサブセット化し、条件を満たすすべての行を保持するために使用されます。保持するには、行がすべての条件に対してTRUEの値を生成する必要があります。条件が NA と評価されると、[を使用した基本サブセット化とは異なり、行は削除されることに注意してください。

filter()の使い方

filter()の使い方は次になります。


filter(.data, ..., .by = NULL, .preserve = FALSE)

filter()の引数の意味

.data

データフレームを指定します。

真偽値を返す式を指定します。
.data内の変数に基づいて定義されます。複数の式が含まれている場合は、&演算子で結合されます。すべての条件がTRUEと評価される行のみが保持されます。

.by = NULL

実験的な引数です。
オプションで、この操作のみでグループ化する列の選択を指定します。
group_by()の代替として機能します。詳細と例については、?dplyr_byを参照してください。

.preserve = FALSE

.data入力がグループ化されている場合に関連します。.preserve = FALSE(デフォルト)の場合、グループ化構造は結果データに基づいて再計算され、それ以外の場合はグループ化はそのまま維持されます。

filter()の戻り値

.dataと同じタイプのオブジェクトが返されます。

filter()の比較・論理演算

filter()の引数には、真偽値を返す式を記述します。この真偽値を返す式には、比較演算子や論理演算子が多用されます。これらの演算子になじみがない方は、あらかじめ当サイトのR入門 ヘルプを参照しておいてください。

準備

あらかじめ、tidyverseパッケージを読み込んでおきます。


library(tidyverse)

解説のために、次のirisデータセットを使用します。


iris |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

数値の大小評価

irisデータセットで、列Sepal.Lengthの値が7.5より大きい行を取得するには次のようにします。


iris |>
  filter(Sepal.Length > 7.5) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
1          7.6         3.0          6.6         2.1 virginica
2          7.7         3.8          6.7         2.2 virginica
3          7.7         2.6          6.9         2.3 virginica
4          7.7         2.8          6.7         2.0 virginica
5          7.9         3.8          6.4         2.0 virginica
6          7.7         3.0          6.1         2.3 virginica

irisデータセットで、列Sepal.Lengthの値が7.5以上7.6以下の行を取得するには次のようにします。


iris |>
  filter(Sepal.Length >= 7.5, Sepal.Length <= 7.7) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
1          7.6         3.0          6.6         2.1 virginica
2          7.7         3.8          6.7         2.2 virginica
3          7.7         2.6          6.9         2.3 virginica
4          7.7         2.8          6.7         2.0 virginica
5          7.7         3.0          6.1         2.3 virginica

これは、「,」区切りは「&」での評価になるため、次のようにしても同じです。


iris |>
  filter(Sepal.Length >= 7.5 & Sepal.Length <= 7.7) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
1          7.6         3.0          6.6         2.1 virginica
2          7.7         3.8          6.7         2.2 virginica
3          7.7         2.6          6.9         2.3 virginica
4          7.7         2.8          6.7         2.0 virginica
5          7.7         3.0          6.1         2.3 virginica

さらに、以上・以下のような範囲による評価の場合はbetween()を使用することもできます。between()を使用するコードの方がややすっきりとした印象です。


iris |>
  filter(between(Sepal.Length, 7.5, 7.7)) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
1          7.6         3.0          6.6         2.1 virginica
2          7.7         3.8          6.7         2.2 virginica
3          7.7         2.6          6.9         2.3 virginica
4          7.7         2.8          6.7         2.0 virginica
5          7.7         3.0          6.1         2.3 virginica

irisデータセットで、列Sepal.Lengthの値がSepal.Widthの2倍より大きい行を取得するには次のようにします。filter()の引数は真偽値を返す式を指定するので、式の両辺に列が含まれていても問題ないことを確認してください。


iris |>
  filter(Sepal.Length > 2 * Sepal.Width) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
1          7.0         3.2          4.7         1.4 versicolor
2          6.9         3.1          4.9         1.5 versicolor
3          5.5         2.3          4.0         1.3 versicolor
4          6.5         2.8          4.6         1.5 versicolor
5          5.7         2.8          4.5         1.3 versicolor
6          4.9         2.4          3.3         1.0 versicolor

数値の完全一致または完全不一致評価

irisデータセットで、列Sepal.Lengthの値が5.5と等しい行を取得するには次のようにします。


iris |>
  filter(Sepal.Length == 5.5) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
1          5.5         4.2          1.4         0.2     setosa
2          5.5         3.5          1.3         0.2     setosa
3          5.5         2.3          4.0         1.3 versicolor
4          5.5         2.4          3.8         1.1 versicolor
5          5.5         2.4          3.7         1.0 versicolor
6          5.5         2.5          4.0         1.3 versicolor

実のところ、浮動小数点の数値で等しいを判定することは誤差の関係でややこしい問題です。そのため、より安全に比較する方法として、near()を使用した方法があります。基本的には、near()を用いた方法をおすすめします。


iris |>
  filter(near(Sepal.Length, 5.5)) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
1          5.5         4.2          1.4         0.2     setosa
2          5.5         3.5          1.3         0.2     setosa
3          5.5         2.3          4.0         1.3 versicolor
4          5.5         2.4          3.8         1.1 versicolor
5          5.5         2.4          3.7         1.0 versicolor
6          5.5         2.5          4.0         1.3 versicolor

irisデータセットで、列Sepal.Lengthの値が5.5と等しくない行を取得するには次のようにします。


iris |>
  filter(Sepal.Length != 5.5) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

等しくない場合も同様に、near()を使用して次のように書けます。


iris |>
  filter(!near(Sepal.Length, 5.5)) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

文字列の完全一致または完全不一致評価

irisデータセットで、列Speciesの値がversicolorと等しい行を取得するには次のようにします。


iris |>
  filter(Species == "versicolor") |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
1          7.0         3.2          4.7         1.4 versicolor
2          6.4         3.2          4.5         1.5 versicolor
3          6.9         3.1          4.9         1.5 versicolor
4          5.5         2.3          4.0         1.3 versicolor
5          6.5         2.8          4.6         1.5 versicolor
6          5.7         2.8          4.5         1.3 versicolor

irisデータセットで、列Speciesの値がversicolorと等しくない行を取得するには次のようにします。


iris |>
  filter(Species != "versicolor") |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

%in%演算子による文字列の完全一致または完全不一致評価

irisデータセットで、列Speciesの値がsetosaまたはversicolorと等しい行を取得するには次のようにします。


iris |>
  filter(Species == "setosa" | Species == "versicolor") |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

これは、%in%演算子を使用して次のように書き換えることができます。


iris |>
  filter(Species %in% c("setosa", "versicolor")) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

irisデータセットで、列Speciesの値がsetosaまたはversicolorと等しくない行を取得するには次のようにします。


iris |>
  filter(!(Species == "setosa" | Species == "versicolor")) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
1          6.3         3.3          6.0         2.5 virginica
2          5.8         2.7          5.1         1.9 virginica
3          7.1         3.0          5.9         2.1 virginica
4          6.3         2.9          5.6         1.8 virginica
5          6.5         3.0          5.8         2.2 virginica
6          7.6         3.0          6.6         2.1 virginica

これは、%in%演算子を使用して次のように書き換えることができます。


iris |>
  filter(!(Species %in% c("setosa", "versicolor"))) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
1          6.3         3.3          6.0         2.5 virginica
2          5.8         2.7          5.1         1.9 virginica
3          7.1         3.0          5.9         2.1 virginica
4          6.3         2.9          5.6         1.8 virginica
5          6.5         3.0          5.8         2.2 virginica
6          7.6         3.0          6.6         2.1 virginica

文字列の部分一致または部分不一致評価

irisデータセットで、列Speciesの値がsicを含む行を取得することを考えます。これにはtidyverseパッケージに含まれているstringrパッケージのstr_detect()を使用するのが簡単です。str_detect()を使用したコードは次です。


iris |>
  filter(str_detect(Species, "sic")) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
1          7.0         3.2          4.7         1.4 versicolor
2          6.4         3.2          4.5         1.5 versicolor
3          6.9         3.1          4.9         1.5 versicolor
4          5.5         2.3          4.0         1.3 versicolor
5          6.5         2.8          4.6         1.5 versicolor
6          5.7         2.8          4.5         1.3 versicolor

irisデータセットで、列Speciesの値がsicを含まない行を取得することを考えます。これにはtidyverseパッケージに含まれているstringrパッケージのstr_detect()を使用するのが簡単です。str_detect()を使用したコードは次です。


iris |>
  filter(!str_detect(Species, "sic")) |>
  head()

  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

欠損値NAを持つ行の取得

欠損値NAを持つ行の取得を考えます。まず、サンプルデータフレームを準備します。


df <- data.frame(
    A = c("a", NA, "c", "d", "e"),
    B = c("A", "B", NA, NA, "E"),
    C = c(1, 2, 3, 4, 5)
  )

サンプルデータフレームの列Aが欠損値NAである行を取得するには次のようにします。


df |>
  filter(is.na(A)) |>
  head()

     A B C
1 <NA> B 2

欠損値NAを持たない行の取得

欠損値NAを持たない行の取得は、当サイトR入門 データフレームの欠損値を除外する方法を参照ください。

R入門 データフレームから条件を満たす行を取得