library(tidyverse)それではだいぶ間があきましたがfilter関数で文字列をひっかけるための処理をここで実践していきましょう
filter関数の練習問題の最後で解説した内容を改めてここで記載します。
temp <- tibble(
name = c("apple","apricot","banana","cherry"),
price = c(120,200,98,300)
)
temp# A tibble: 4 × 2
name price
<chr> <dbl>
1 apple 120
2 apricot 200
3 banana 98
4 cherry 300
で、aで始まるname列のみに絞りこみたい、aで終わるname列のみに絞りこみたいという場合はどうしたらよいでしょうか?
ここまで学んでいただいた内容からは、
- 列の絞りこみにはfilter関数を利用する。
- filter関数の中に与えるロジカルベクトルをstr_detectで作成する
- str_detectの中の正規表現を絞り込みたい条件に沿って作成する
という3つのステップを違和感なく理解することができるはずです。
この3つのステップをスクリプトで記載すると
aで始まる行のみに絞り込む:
temp %>% filter( str_detect(name,"^a") )# A tibble: 2 × 2
name price
<chr> <dbl>
1 apple 120
2 apricot 200
aで終わる行のみに絞り込む
temp %>% filter( str_detect(name, "a$"))# A tibble: 1 × 2
name price
<chr> <dbl>
1 banana 98
です。
他の活用例も確認しておきましょう。
str_detectを使うと、数字のはずなのに、文字列が混ざっているような行を見つけることも簡単です。
temp2 <-
tibble(
kensa = c("a","a","b","b","c","c"),
value = c(100,200,"3OO","400","未","500")
)
temp2# A tibble: 6 × 2
kensa value
<chr> <chr>
1 a 100
2 a 200
3 b 3OO
4 b 400
5 c 未
6 c 500
こんなデータがあったとして、仮にこれが数万行のデータで、手入力されたものであった場合、入力時点での規制がかけられていない場合、多くの場合に、「想定外」のものが紛れ込んでいます。
本来、valueの列には数字しか入っていてほしくないはずなのですが、本当にそうか確認したい場合、
temp2 %>% filter( str_detect(value, "^\\d+$") )# A tibble: 4 × 2
kensa value
<chr> <chr>
1 a 100
2 a 200
3 b 400
4 c 500
そうあってほしい正規表現をかくとこのように数字ではじまり、数字でおわり、数字以外の文字列がない行を拾うことができます。
!c(TRUE,FALSE)[1] FALSE TRUE
で、TRUEとFALSEを逆にできること、覚えていますか?
str_detect(c("ab","ba","bb"),"^a")[1] TRUE FALSE FALSE
!str_detect(c("ab","ba","bb"),"^a")[1] FALSE TRUE TRUE
このように、str_detectはロジカルベクトルを返すので前に!をつけることで結果をひっくり返すことができます。なので、
temp2 %>% filter( !str_detect(value, "^\\d+$") ) # A tibble: 2 × 2
kensa value
<chr> <chr>
1 b 3OO
2 c 未
こんな感じで、「!そうあってほしい」結果をfilter関数の中に投入すると、実は「3オーオー」と「未」という数字以外の結果が紛れていることが判明します。
他にも、汚いデータの処理で注意が必要なのが全角数字の処理です。
全角数字は、\d+では認識されてしまうのですが
str_view("1234","\\d+")[1] │ <1234>
str_detect("1234","\\d+")[1] TRUE
数値変換しようとすると失敗します
as.numeric("1234")[1] 1234
as.numeric("1234")Warning: NAs introduced by coercion
[1] NA
なので全角数字が混じっている可能性があるデータなのであれば、\d+よりも、[0-9]と書いてあげる方が適切です。
str_view("1234","[0-9]")
str_detect("1234","[0-9]")[1] FALSE
str_view("1234","[0-9]+")[1] │ <1234>
temp3 <- tibble(
num = c(111,"112",213,"132",323,"433",445,"445",358,"857",654,"766",778,"978",865,"867",596,"769",506,"607")
)
temp3# A tibble: 20 × 1
num
<chr>
1 111
2 112
3 213
4 132
5 323
6 433
7 445
8 445
9 358
10 857
11 654
12 766
13 778
14 978
15 865
16 867
17 596
18 769
19 506
20 607
temp3 %>% filter( str_detect(num,"^[0-9]+$"))# A tibble: 10 × 1
num
<chr>
1 111
2 213
3 323
4 445
5 358
6 654
7 778
8 865
9 596
10 506
temp3 %>% filter( !str_detect(num,"^[0-9]+$"))# A tibble: 10 × 1
num
<chr>
1 112
2 132
3 433
4 445
5 857
6 766
7 978
8 867
9 769
10 607
以上、str_detectとfilterを組み合わせて利用する方法を紹介しました。