R の filter 関数:
データフレームの行を選択する

UBC/informatics/r/filter

このページの最終更新日: 2024/02/24

  1. 概要: filter() 関数とは
  2. 基本的な使い方
  3. filter() 関数に変数を含める (for loop 内で filter() 関数を使う)
  4. その他メモ

広告

概要: filter 関数とは

filter 関数は、データフレームから行を抽出する R の関数である。dplyr という パッケージ に含まれており、R のデフォルト関数ではないので、インストールされていないならまず install.packages("dplyr") でインストールし、library(dplyr) で読み込んでから使う。

以下のようなページと関連が深い。

tidyverse を読み込むと dplyr::filter() masks stats::filter() という表示が出る。これは、stat というパッケージにも filter という関数があること、tidyverse がそれを立ち上げないように mask していることを意味している。

したがって、単に filter で十分であるが、dplyr::filter という書き方の方がさらに安心である (参考)。このサイトでは、省略している部分もあるが、なるべく dplyr::filter という表記で統一する。

基本的な使い方

文字列の一致

組み込みデータセット chickwts を使って試してみる。これは horsebeanm, linseed などの餌を与えられて育ったニワトリの体重データである。

R 組み込みデータセット chickwts

ここから feed が horsebean の行のみを取り出すには、

dplyr::filter(.data = chickwts, feed %in% c("horsebean"))

とする。まず .data でデータセットを指定する。その次には論理式がくる。A %in% B は R baseにある演算子で、「B の要素のどれか 1 つにマッチしたら TRUE、どれにもマッチしなければ FALSE」を返す (1)。filter 関数と共によく使われる。feed %in% c("horsebean") で、feed が horsebean である行のみを取り出せることになる。

これはもっと単純に、

dplyr::filter(chickwts, feed == "horsebean")

でも同じ結果になるが、次の例を考えると、%in% の方が応用の範囲が広く、こちらで覚えておくべきだろう。

ベクターのいずれかと一致

文字列が複数あるときは、ページ下の 複数の条件を指定する のように書いても良いが、%in% をベクターにすれば「ベクターのいずれかと一致」する行を抽出できる。

dplyr::filter(.data = chickwts, feed %in% c("horsebean", "linseed"))


文字列の部分一致

いくつか方法はあるが、stringr パッケージの str_detect 関数を使う方法が便利である。feed から l を含む行のみを抽出する例を示す。

dplyr::filter(.data = chickwts, str_detect(feed, "l"))

str_detect で、ベクターを使いたい場合は、paste() または paste0() を使う。collapse = "|" は「または」、つまり horse か lin のいずれかの文字列が feed に含まれる行が選択される。

vector <- c("horse", "lin")
dplyr::filter(.data = chickwts, str_detect(feed, paste0(vector, collapse = "|")))

数値の大小など

数値の大小で指定することもできる。

dplyr::filter(chickwts, weight > 400)

複数の条件を指定する

複数の条件をカンマ , で繋ぐと and 指定 (条件 A かつ 条件 B)、| で繋ぐと or 指定 (条件 A または 条件 B) になる。

dplyr::filter(chickwts, weight > 400, feed == "casein")

filter 関数に変数を含める

for loop に filter 関数を組み込みたい場合など。

まず、上の例で feed をベクターにすると、該当する行が見つからない。つまり、feed の部分にはベクターを入れることはできない。

同様に、c("feed") をオブジェクトとして保存し、これを filter 関数に含めてもダメ。

c("feed") をオブジェクトとして保存し、paste 関数、paste0 関数を使ってもダメだった。

正しくは、このように 二重かぎかっこを使う。chickwts[[A]] とすると、変数 A を読み込んだ行指定になる。

chickwts[["A"]] だと、A の変数を読み込まずに A という行を探すのだろう。これはエラーになる。

この推察が正しいことを裏付けるように、chickwts[[feed]] はエラーになり、chickwts[["feed"]] は chickwts[[A]] と同じ結果になる。

これを for loop に組み込んでみる。

パターン 1 では、for loop は回るものの、なぜか何も出力されない。

パターン 2 のように、一度 filter の結果をオブジェクトに格納し、それを print すると、予想通りの結果になる。print のかわりに解析を追加すれば、for loop の中に filter を組み込めることになる。

これは、paste0 関数を入れても大丈夫。これを利用すると、たとえば feed1, feed2... という列がある場合に、入れ子の for loop にすることも可能になる。

その他メモ

library dplyr を読み込んでいないと、なぜか filter 関数が見つからないというエラーではなく、オブジェクトが見つからないというエラーが出る。以下のような感じ。

Error in Blood_type %in% c("A")) : object 'Blood_type' not found


広告

References

  1. 行の選択 - filter関数. Link: Last access 2022/05/24.
  2. dplyrで変数を使いfor文で繰返し処理を行う方法. Link: Last access 2022/10/18.
  3. 【R】データフレームをフィルタリングする方法|filter関数. Link: Last access 2022/10/18.

コメント欄

サーバー移転のため、コメント欄は一時閉鎖中です。サイドバーから「管理人への質問」へどうぞ。