086 str_extractとmutate
str_exrtact
とmutate
str_extract
ここまでは、booleanで正規表現を返す、str_detect()
で話を進めてきました。
行操作には、str_detect
で引っかけるという作業が必要ですが、例えば、
prac <- tibble(target = vec) View(prac)
- というデータがあって、抜き出した結果を新しい列として入れたいという場合は
str_extract()
を利用します。
str_extract(vec,"(\\d+\\.\\d+)|\\d+")
- はベクトルが帰ってきます。(そして、マッチしない場合は、NA)
- mutateにベクトルを放り込むと列ができることは覚えていますか?というわけで
prac <- prac %>% mutate(nukidasi = str_extract(target, "(\\d+\\.\\d+)|(\\d+)")) library(tidyverse) #library(stringr) prac <- prac %>% mutate(with_unit = str_extract( target, "((\\d+\\.\\d+)|(\\d+))(?=((mg)|(ml)))" ))
- で抜き出すことができました
081-085 正規表現
正規表現
- さあ、filterへ!といきたいところでえすが、もう一山、Booleanが「しるし」になることを理解したあと、文字列に「しるし」をつける方法を学びましょう。
- 正規表現というものですが、これは、多分、このコースでもかなりとっつきにくい部類に入ります。
- たとえば、次の文字列から、数字だけを抜き出したい場合にどのような方法がとれるでしょう?
vec <- c("HbA1c:9.2%","ALT:120UI","WBC:9.3x10^3")
- いままでにお伝えしたものでは無理です。
- ここから、このような、文字配列的に汚いデータから欲しいデータを抜き出す方法、正規表現を学びましょう。
#ちなみに、上記の問題は、 library(stringr) str_extract(vec, "(?<=:)(\\d+\\.\\d+)|(?<=:)\\d+")
- で達成できます。
正規表現とは
正規表現は文字列をパターンでひっかける手法です。
注:
vec <- c("1","120","34.3","ab123", "5b","6 5","7","b","ac4235432", "45.3mg/dl","abc500ml 3unit 3:40AM", "^ is start.", "this sign($) represents end.", "....") vec
- たとえば、"1"という文字が含まれているかどうかを調べたければ、
str_detect()
を使います。
str_detect(vec,"1") #[]をつかって抜き出してみましょう。 vec[str_detect(vec,"1")] #尚、複数の文字列をひっかけたい場合は、"[1234]"のように書きます。 check <- str_detect(vec,"[1234]") vec[check]
正規表現を色々確認してみる
- 何が引っ掛かったかみたい場合は、str_view()を使うとわかりやすいです。
str_view(vec,"[1234]") str_view(vec,"[1234567890]") str_view(vec,"[0-9]") #二文字引っ掛かったかは、 str_view(vec,"[0-9][0-9]") str_view(vec,"[0-9]{1,}") #数字が連続した場合を調べるには str_view(vec,"[0-9]+") #x回数以上y回数以下を調べるには str_view(vec,"[0-9]{3,4}") #[0-9] と \\dは同じ意味です。 str_view(vec,"\\d+") #「なんでもよい」場合は.で表現できます。 str_view(vec,".") str_view(vec,".+") #パターンの開始が文字列の先頭にあるかを^で調べることもきます。 str_view(vec,"^b") #同様に最後は$です。 str_view(vec,"\\d{3}$") #^と$ str_view(vec,"^b$") str_view(vec,"^\\d+$") #ところで、.とか^とか$とかを str_view(vec,"^") #ひっかけるにはどうしたらいいでしょうか?\\でエスケープ str_view(vec,"\\^") str_view(vec,"\\$") str_view(vec,"\\.+")
正規表現で小数点がある数字だけ抜き出してみる
- ここまでの知識で、最初の少数点のみ抜き出すということが実現できます。
- 143.23 は、
\\d+\\.\\d+
で拾えるので、
str_view(vec,"\\d+\\.\\d")
- でも、これだと少数点がついていないケースはだめですね
\\d+
のみのパターンに対しては|
をつかいます。\\d+\\.\\d+ | \\d+
str_view(vec,"\\d+\\.\\d+ | \\d+") #これだとうまくいきません
- 「 」スペースも文字なので、
str_view(vec," ") str_view(vec,"\\d+\\.\\d+|\\d+") str_view(vec,"(\\d+\\.\\d+)|(\\d+)") str_view(vec,"a(b|c)") str_view(vec,"(ab)|(c)")
正規表現の練習
- 次のような文字列から、欲しい数字を抜き出すにはどうしますか?
exa <-"room200 3unit AM3:40 abc300ml"
- "abc300ml"が何らかの点滴の名前だとして、300mlの300を抜き出したいとすると、
str_view(exa,"\\d+") #X
- 条件をつけます!
- パターンA(?=パターンB)で、「パターンAパターンB」がひっかかる部分のパターンAを抜き出す。という操作ができます
str_view(exa,"\\d+(?=ml)")
- (?<=パターンA)パターンBだと<の開いている方向に
- (?=)と同様のことができます。
str_view(exa,"(?<=room)\\d+") str_view(exa,"(?<=abc)\\d+") str_view(exa,"\\d+(?=ml)") str_view(exa,"\\d+(?=unit)") #その他 str_view(vec,"\\w+") #すべての文字 str_view(vec,"\\W+") #すべての非文字 str_view(vec,"\\d+") #すべての数字 str_view(vec,"\\D+") #すべての非数字 str_view(vec,"\\s+") #スペース str_view(vec,"\\S+") #非スペース
- もっと深く知りたいという方はstringrのチートシートをRstudioのサイトからダウンロードしてみてください。
077-080 Logical/Boolean型
Logical/Boolean型
これまでの型:
- 数字:1, 2, 3, 10.4, 100 …
- 文字列: “Rは楽しい”, “Hi there!”…
Logical/Boolean:
TRUE
かFALSE
の二通りのみをとれる型- TRUE/FALSEで真偽の「判定」を行うのに活用
単独での動作
TRUE FALSE TRUE + TRUE TRUE + FALSE FALSE + FALSE
TRUE
の正体は「1」です。- このBooleanが出現するのは、「判定」をRの中で実施したときです。
- "ごはんが美味しい" という文字列 と "味噌汁が美味しい" という文字列は同じ(==)かという場合は
"ごはんが美味しい" == "味噌汁が美味しい"
- FALSEですね。(内容は関係ないです)他にも、
450 == 450 431 == 4
- 当たり前といえば当たり前の結果になります。
- 「=」が2つなのに注意が必要です。
340 = 340
- 実は、= は <- と同じ意味をもっていて、上の例では、340という変数に340を代入しようとしたものの、数字に別の意味は持たせられない!とおこられました。
a <- 10 a b = 10 b
- ただし、=での代入は非推奨で、<-を使うことが広く推奨されています。(->)
- なぜかは知りません。
a == b
- != という記号は、「同じでない」を示します。
450 != 90 340 != 340 "ごはんが美味しい" == "味噌汁が美味しい" "ごはんが美味しい" != "味噌汁が美味しい"
- 他、 > < >= <= も数学的な比較と同じ意味合いで利用できます。
34 < 34 34 <= 34 35 > 35 35 >= 35 a <- 10 a < 1 b <- 100 a < b
等々
vectorでのロジカル
- ベクトルも比較演算子でLogicalの形で表せます
vec <- c(1:20) vec vec == 1 1 == vec vec > 10 vec < 5
A が Bに含まれるか? というものを調べるには、 A %in% B
を使います。
c(1,2,3,4,5) %in% c(3,4) c(3,4) %in% c(1,2,3,4,5)
- 本当は、大抵のRコースで最初に学ぶことをここで紹介します。
vec
から特定の値を抜き出したい場合には、<ベクトル>[<booleanのベクトル>]
という表現でできます。
vec <- c(1:5) vec[c(TRUE, TRUE, TRUE, TRUE, TRUE)] vec[c(TRUE, TRUE, TRUE, TRUE, FALSE)] vec[c(TRUE, TRUE, FALSE, TRUE, FALSE)] vec[c(FALSE, TRUE, FALSE, TRUE, FALSE)]
- ということは、
vec > 3 vec[vec > 3]
- という感じでベクトルから取り出すことができます。
- 「ロジカルのベクトル」は「ベクトルからその要素を取り出すとき」に多用するものとなります
<><=>=&|
TRUE & TRUE #TRUE TRUE & FALSE #FALSE FALSE & FALSE #FALSE TRUE & TRUE (5 == 5) (7 > 3) 5==5 & 7>3 TRUE | TRUE #TRUE TRUE | FALSE #TRUE FALSE | FALSE #FALSE
>
,<
,>=
,<=
,==
,!=
,&
,|
,!
- これらの記号を組み合わせて、条件設定を考えることが、行の操作で非常に重要になります。
- 行操作は列操作と違い、時に何万というデータに対してTRUEとFALSEを振り分けて、TRUE/FALSEを抽出・加工するという作業になります。
どんな文字列が含まれたベクトルに対しても、思うようにTRUE, FALSEが設定できるようになると、データクリーニングは自由自在にできるようになります。
そのために、たとえば、
vec <- c(NA,1,2,3,NA,4,5,6) vec[is.na(vec)] #でNAをとりだしたり(意味ない・・・) vec[!is.na(vec)] #でNAを除去したり。
- のようなことができるようになると良いです。
- 実は[]を利用したベクトル操作が、Rの王道ではありますが、tidyverseのエコシステムが非常に便利なので、この講義ではあんまり出てきません。
076 arrange:行の並び替え
arrange:行の並び替え
- arrangeは、行方向でのソート(並び替え)を行う関数
test #このtibbleを、身長順に並び替えるには? test %>% arrange(height) #昇順 test %>% arrange(desc(height)) #降順
- desc = descending(下降する) <=> ascending(上昇する)
- 複数指定した場合に、指定した順番でグループ化されて並び替えられます。
test3 <- tibble(grp1 = c(rep(c(1:10),2), rep(c(10:1),2)), grp2 = c(rep(c(5:1),4), rep(c(1:5),4)), grp3 = c(rep(c("a","b","c","d"),10)) ) test3 View(test3)
- このようなtibbleがあったとして、
test3 <- test3 %>% arrange(grp1) test3 <- test3 %>% arrange(grp2) test3 <- test3 %>% arrange(grp3) test3 <- test3 %>% arrange(grp1, grp2) test3 <- test3 %>% arrange(grp2, grp1) test3 <- test3 %>% arrange(desc(grp3), grp1) test3 <- test3 %>% arrange(desc(grp3), desc(grp1)) test3 <- test3 %>% arrange(desc(grp3), grp2, grp1)
- と、このような感じで利用します。
073-075 列の操作(mutate、rename、select)
列の操作
mutate:列の作成
library(tidyverse) test <- tibble(umare = c(1990, 1992, 1997, 1991), height = c(180.0, 176.2, 165.5, 172.3), weight = c(70.2, 80.3,65.3,61.1)) test
- mutateは、新しい列をつくる関数です。
mutate(.data = <tibble>, <新しい列名> = <ベクトル> )
mutate(.data = test, ima = 2018) test test <- test %>% mutate(new = "new!!")
- "new!"は長さが1のベクトルです。
test
- このように、ベクトルを入れると、
- 自動的に複製されて、列ができあがります。
test <- test %>% mutate(new2 = c("a","b","c"))
- ただし、ベクトルの長さは、自動的に変換してくれません
- ぴったり か、 長さ1 である必要があります。
- ベクトル同士の計算も、簡単にできます
test <- test %>% mutate(name = c("鈴木一郎","本田次郎", "豊田三郎","日本四郎")) %>% mutate(nyusya = 2018) %>% mutate(age_at_nyusya = nyusya - umare) test
- プチ課題:height(身長), weight(体重)から、bmi(body mass index)を計算してみてください。
- 尚、BMIの計算式は、
体重[kg] ÷ (身長[m] * 身長[m])
です。 - Rでは、 割り算を / 身長の2乗は、身長2 のように記載します。
test <- test %>% mutate(bmi = weight/{(height/100)^2}) test
rename(列名の変更)
- 作った列の名前を変えたいと思ったときには、
rename()
関数を利用します。rename(<新しい名前> = <対象となる列の名前>)
test <- test %>% rename(birth_year = umare) test
select(列の選択)
- 列を選択したい場合は、
select(<列の名前>,<列の名前>,<列の名前>,....)
という記載を行います。
test %>% select(birth_year, height) #で二つだけ。 test %>% select(-new, -nyusya, -height, -weight) #-<名前>で除外することもできます。
- よく使う、
select()
での列選択の方法に、starts_with()
,ends_with()
,contains()
,everything()
などがあります。
test2 <- tibble(v1 =c(10:20), v2_99=c(20:30), v100=c(30:40), x1=c(40:50), x2_30=c(50:60), x31 =c(31))
- このように、変数名が一定の規則をもって並んでいる場合に、「v」で始まる変数だけ取得したいケース
test2 %>% select(starts_with("v")) test2 %>% select(starts_with("x"))
*「1」で終わる変数だけ取得したいケース
test2 %>% select(ends_with("1"))
- なんでもよいので、「0」が含まれている変数を取得したいケース
test2 %>% select(contains("0"))
- すべてを選ぶ、everything()
test2 %>% select(everything())
- 何のやくにたつの?という感じですが、並び替えに威力を発揮します。
- x31を一番前に持っていきたいときは、
test2 %>% select(x31, everything()) #このように、x31以外のすべてが選ばれるので、並び替えができます。
selectの演習問題
課題1
- 「test」tibbleで、「b」が変数名に含まれるものを抜き出してください。
test %>% select(contains("b"))
課題2
- 「test2」tibbleで、vではじまる変数と、xではじまる変数の順番を入れ替えてください。
test2 %>% select(starts_with("x"), starts_with("v"))
課題3
- 「test2」tibbleで、変数を逆に並び替えてください
test2 %>% select(v100, v2_99, v1, x31, x2_30, x1)
- ですが、もし本物のデータであれば、
test2 %>% select(x31, x30, x29, ..., x2, x1, v100, v99, v98, v97, ..., v2, v1)
- と、非常に面倒です。
test2 %>% select(c("v100","v1"))
- このように、文字列ベクトルでの指定もOKなので、colnames()関数を利用して、楽に入れ替えしてみましょう。
retumei <- colnames(test2) retumei rev(retumei) test2 %>% select(rev(retumei)) #新しい変数を作りたくなければ、 test2 %>% select(rev(colnames(test2))) #ということも可能です。
- ちょっと読みにくいので、{ }でくくって処理を別であると明記して、
test2 %>% select({test2 %>% colnames() %>% rev()})
- でもOKです。
072 パイプ
パイプ(%>%)
- Ctrl + Shift + M で入力可能。
library(tidyverse) diamonds$carat summary(diamonds$carat) # 上の行と下の行は同じ処理 diamonds$carat %>% summary()
- パイプを利用すると何が嬉しいかというと、
add(multiply(subtract(divide(3,4))))
こんな風に、関数の処理結果を別の関数にそのままわたしたい場合に、 括弧の中に入れる方法だと、内側から外側に処理の順番が並ぶことになりますが、 パイプを利用することで、処理の順番に関数名を書くことができ、見通しがよくなります。
divide(3,4) %>% subtract() %>% multiply() %>% add()