R言語による医療データ分析

R言語によるデータ分析のオンラインコースを中心に、さまざまなデータ分析について記載してあります。

086 str_extractとmutate

まとめ一覧

str_exrtactmutate

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: TRUEFALSEの二通りのみをとれる型

  • 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()

まとめ一覧

070 messy->tidyへの変換イメージ

まとめ一覧

messyデータをtidyデータに変換するイメージ

このデータを

f:id:tentencon:20191221163326j:plain
frommessy

こんな感じになるようにします。

f:id:tentencon:20191221163624j:plain

(詳細なステップは、動画で確認ください)

今後、解説する関数は次のような形です

f:id:tentencon:20191221163706j:plain

まとめ一覧