Press "Enter" to skip to content

[R] 条件によるフィルタリング

wyosis 0

http://r4ds.had.co.nz/transform.html#filter-rows-with-filter

filter関数の使い方

とりあえず、

library(tidyverse)
library(nycflights13)

を読み込み、

filter(flights, month == 1, day == 1)

としてみる。すると、flightsのデータから1月1日のものだけを抽出することができる。ただし、量が多くて省略されるかもしれない。引数の意味を1つ目から説明すると、

  1. flights … 対象とするデータフレーム
  2. month == 1 … フィルタリング条件1(monthが1のもの)
  3. day == 1 … フィルタリング条件2(dayが1のもの)

決まりごととして、引数の一つ目はデータセットで2つ目以降は条件を並べていく。

dplyrに共通することだが、対象となるデータフレームはfilterなどの関数によって変更されるということはない。したがって、抽出結果を残したければ、

jan1 <- filter(flights, month == 1, day == 1)

のようにして代入する必要がある。逆に言えば、関数を使用することによって元のデータが汚れるようなことはないということである。ちなみに、気づいた人もいるかもしれないが、代入すると抽出結果が表示されない。代入と同時に結果の表示をしたい場合は、

(dec25 <- filter(flights, month == 12, day == 25))

のようにするとうまいくいく。

条件演算子

C言語などを触っている人は条件演算子が何なのかというのは既に理解しているとは思う。簡単に説明すると、上で出てきたような==(等しい)のような記号のことである。RにはC言語と同様の演算子が用意されている。

  • x > y … xがyより大きい
  • x >=y … xがy以上
  • x < y … xがyより小さい
  • x <= y … xがy以下
  • x != y … xとyが等しくない
  • x == y … xとyが等しい

filter関数の第二引数以降はこれらの条件演算子を用いて条件を指定していくことになる。よくある間違いとして===としてしまうのがある。エラーになってしまう。

filter(flights, month = 1)

また、あらゆる場所で注意するべきだが、プログラミング上の計算は数学のそれと必ずしも同じになるとは限らない。

sqrt(2) ^ 2 == 2

1/49 * 49 == 1

上記の2例は数学では左辺と右辺が等しくなるはずである。しかし、どちらも結果はFalse(正しくない)である。なぜならば、コンピュータ上ではsqrt(2)や1/49といった無限小数は適当な桁で近似されてしまうからである。イメージとしては、sqrt(2)が1.414のようになってしまうのである。すると1.414の二乗は1.9993…となり、2にならないので、==演算子はFalseという結果を返す。その代わり、値が近いことを評価するnear関数を使うとTRUEを返してくれる。

near(sqrt(2) ^ 2, 2)
near(1 / 49 * 49, 1)

集合

集合をどこかで学んだことがある人はそれを思い出して欲しい。概要は以下の図でわかると思う。補足すると、

  • x & y … かつ。yとxの条件を同時に満たす
  • x | y … または。xとyのどちらかの条件を満たす
  • xor(x, y) … xとyの条件を同時に満たさない
  • !x … xでない

※& や | を論理演算子という。

Complete set of boolean operations. `x` is the left-hand circle, `y` is the right-hand circle, and the shaded region show which parts each operator selects.

(CC by http://r4ds.had.co.nz/transform.html#filter-rows-with-filter, Garrett Grolemund, Hadley Wickham)

実際にこの図を思い浮かべながらフィルタリングをしてみる。

filter(flights, month == 11 | month == 12)

上の例は11月か12月に出発した飛行機のデータを表示する。ちなみに上記のコードの引数は2つである。第二引数に| (または)でつないだ条件が入っているのである。

次のような書き方は想定しているものとは異なる結果を出す。

filter(flights, month == 11 | 12)

あくまで、論理演算子の前後に条件式を書く必要がある。もし、略式で書きたければ次のような書き方もある。

nov_dec <- filter(flights, month %in% c(11, 12))

x %in% y はベクトルyの中のどれか1つにでもxが等しいかを見る。つまり、11月か12月のデータを抜き出すという意味に他ならない。

集合の最後にド・モルガンの法則を試してみる。

filter(flights, !(arr_delay > 120 | dep_delay > 120))
filter(flights, arr_delay <= 120, dep_delay <= 120)

上記の2例はどちらも同じ集合を表しており、結果も同じになるはずである。

Missing Number(NA)の扱い

Rで特に注意するべきものとして、未知数、データなしを表すNAという値がある。なぜなら、NAに対するあらゆる演算はNAになってしまうからだ。

NA > 5
10 == NA
NA + 10
NA / 0

NA同士の比較もだめ。

NA == NA

NAであることを確かめる関数がある。

x <- NA

is.na(x)

フィルタリングする場合、NAの存在を考慮しないと、意図せずにデータを読み飛ばす場合があるので、明示的に条件に加えることが大事である。その例を示す。

df <- tibble(x = c(1, NA, 3))
filter(df, x > 1)
filter(df, is.na(x) | x > 1)

一行目ではデータフレームを作成している。tibbleは作成用の関数で、この場合x列に1, NA, 3が入ったデータフレームが作成される。そして、2行目はxが1より大きい行の抽出をしている。NAはNAを返すので、当然引っかからない。これはx <= 1としても同様である。NAも検索結果に反映したい場合は、is.naを | に含める必要がある。

 

コメントを残す

メールアドレスが公開されることはありません。