■tidyverse

 

 tidy:整頓、整理された

messy  :やっかいな

 

tidy dataとは

 ・1列が1変数に対応している

 ・1行が1観察に対応している

 ・1観察単位が1つの表を形創る

 

  →tidyでないものはすべてmessyなデータ

%>%(パイプ;関数をつなぐ)  ショートカット:ctrl  + shift + m

手順:

 

library(tidyverse)    #tidyverseを読み込む

 

#pipe:%>%  ショートカットキー ctrl + shift +m

 

 

diamonds$carat

 

summary(diamonds$carat)

 

diamonds$carat  %>% summary   #summary(diamonds$carat)と同じ結果

 

#パイプを使用するとネスト関数など表現がわかりやすくなる

#使用例

#関数のネストがあった場合 →  add(multiply ( subtract ( divide ( 3, 4 )) ) )

#パイプを使用して置き換えた場合 → divide( 3 ,4 ) %>% subtract  %>% multiply  %>% add

 

            

mutate(ミュゥテイト)(列の追加)関数

#例

#<データ test が以下の通りのデータであった場合>

#---------------------------------------------

#    umare height weight

#    <dbl>  <dbl>  <dbl>

#   1  1990   180    70.2

#   2  1992   176.   80.3

#   3  1997   166.   65.3

#   4  1991   172.   61.1

#--------------------------------------------

 

#mutateは、新しい列をつくる関数です。

#mutate(.data = <tibble>, <新しい列名> = <ベクトル> )

 

mutate(.data = test, Cur = 2020)

 

 

#これを実行するだけでは、列は追加されない

 

#---------------------------------------------

#    umare height weight

#    <dbl>  <dbl>  <dbl>

#   1  1990   180    70.2

#   2  1992   176.   80.3

#   3  1997   166.   65.3

#   4  1991   172.   61.1

#--------------------------------------------

 

test <- test %>% mutate(Cur = "Current")

 

#-----------------------------------------------------------

#  umare height weight new   Cur    

#  <dbl>  <dbl>  <dbl> <chr> <chr>  

#1  1990   180    70.2 cur   Current

#2  1992   176.   80.3 cur   Current

#3  1997   166.   65.3 cur   Current

#4  1991   172.   61.1 cur   Current 

#-----------------------------------------------------------

 

#height(身長), weight(体重)から、bmi(body mass index)を計算

#<BMIの計算式>

#体重[kg] ÷ (身長[m] * 身長[m])

#Rでは、 割り算を / 2乗は、^2 と記載します。

 

test <- test %>% 

  mutate(bmi = weight/{(height/100)^2})

 

#    umare height weight new   Cur       bmi

   <dbl>  <dbl>  <dbl> <chr> <chr>   <dbl>

 1  1990   180    70.2 cur   Current  21.7

 2  1992   176.   80.3 cur   Current  25.9

 3  1997   166.   65.3 cur   Current  23.8

 4  1991   172.   61.1 cur   Current  20.6

 

select(列の選択)

#列を選択したい場合は、

#select(<列の名前>,<列の名前>,<列の名前>,....)

#という記載を行います。

 

test %>% select(umare, height) 

 

#-------------------------------

  umare height

  <dbl>  <dbl>

1  1990   180 

2  1992   176.

3  1997   166.

4  1991   172.

#-------------------------------

 

#以下のような表がある場合

#--------------------------------------------------------------------------

#         v1 v2_99  v100    x1 x2_30   x31

#      <int> <int> <int> <int> <int> <dbl>

#   1    10    20    30    40    50    31

#   2    11    21    31    41    51    31

#    3    12    22    32    42    52    31

#    4    13    23    33    43    53    31

#    5    14    24    34    44    54    31

#   6    15    25    35    45    55    31

#    7    16    26    36    46    56    31

#    8    17    27    37    47    57    31

#    9    18    28    38    48    58    31

#   10    19    29    39    49    59    31

#   11    20    30    40    50    60    31

#--------------------------------------------------------------------------

 

test2 %>% select(starts_with("v"))

 

#vで始まる列が取得される。

 

#--------------------------------------------------------------------------

#         v1 v2_99  v100

#      <int> <int> <int>

#    1    10    20    30

#    2    11    21    31

#    3    12    22    32

#    4    13    23    33

#    5    14    24    34

#    6    15    25    35

#    7    16    26    36

#    8    17    27    37

#    9    18    28    38

#   10    19    29    39

#   11    20    30    40

#--------------------------------------------------------------------------

arrange関数

 

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)

 

 

#  grp1  grp2  grp3

1 1 5 a

2 2 4 b

3 3 3 c

4 4 2 d

5 5 1 a

6 6 5 b

7 7 4 c

8 8 3 d

9 9 2 a

10 10 1 b

11 1 5 c

12 2 4 d

13 3 3 a

14 4 2 b

15 5 1 c

16 6 5 d

17 7 4 a

18 8 3 b

19 9 2 c

20 10 1 d

21 10 1 a

22 9 2 b

23 8 3 c

24 7 4 d

25 6 5 a

26 5 1 b

27 4 2 c

28 3 3 d

29 2 4 a

30 1 5 b

31 10 1 c

32 9 2 d

33 8 3 a

34 7 4 b

35 6 5 c

36 5 1 d

37 4 2 a

38 3 3 b

39 2 4 c

40 1 5 d

Showing 11 to 39 of 40 entries, 3 total columns


Boolean/Logical型

 

vec <- c(NA,1,2,3,NA,4,5,6)

 

vec[is.na(vec)] #でNAをとりだし

 

vec[!is.na(vec)] #でNAを除去。

> vec[is.na(vec)] #でNAをとりだし

[1] NA NA

> vec[!is.na(vec)] #でNAを除去。

[1] 1 2 3 4 5 6


正規表現

######################################################

#####データクリーニング###########################

######################################################

 

library(tidyverse)

 

######################################################

#%>%(パイプ; 関数をつなぐ)の説明 

######################################################

 

#Ctrl + Shift + M で入力可能。

library(tidyverse)

#pipe:%>%

 

#shift + ctrl + m

 

diamonds$carat

 

summary(diamonds$carat)

 

diamonds$carat %>% summary()

 

add(multiply(subtract(divide(3,4))))

 

divide(3,4) %>% 

  subtract() %>% 

  multiply() %>% 

  add()

 

######################################################

#mutate(列の追加)の説明 =================================

######################################################

 

 

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, Cur = 2020)

test

 

test <- test %>% mutate(Cur = "Current")

 

 

# "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(列名の変更) とselect(列の選択)の説明 ------------------

######################################################

 

#rename and select==========================================

#mutateで作ったtibbleを引き続き使います。

test

#作った列の名前を変えたいと思ったときには、

#rename()関数を利用します。

#rename(<新しい名前> = <対象となる列の名前>)

 

test <- test %>% 

  rename(birth_year = umare)

 

test

 

#また、列を選択したい場合は、

#select(<列の名前>,<列の名前>,<列の名前>,....)

#という記載を行います。

 

test %>% select(umare, 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))

 

test2

 

#このように、変数名が一定の規則をもって

#並んでいる場合に、「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以外のすべてが選ばれるので、

#並び替えができます。

 

#なお、

test2 %>% select(x31) #はだめです。

 

 

 #####################################################

# arrange(行の並び替え)の説明  --------------------------------

######################################################

 

#arrange ===================================================

#mutate, rename は列への操作でしたが、

#行方向への操作の代表的な関数が、

#filterとarrangeです。

 

#filterは名前の通りに、

#行方向にフィルターをかけて抽出する関数

#arrangeは、行方向でのソート(並び替え)を行う関数

 

#filterを理解するためには、

#Boolean型の理解が必要  

#        ->ここでは、まずarrangeの説明から。

 

test #このtibbleを、身長順に並び替えるには?

 

test %>% arrange(height) #昇順

 

test %>% arrange(desc(height)) #降順 

#desc = descending(下降する) <=> ascending(上昇する) 

 

#複数指定した場合に、

#指定した順番でグループ化されて並び替えられます。

 

library(tiydyverse)

 

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)

 

#と、このような感じで利用します。

 

######################################################

# Logical型:Rでの動作 ---------------------------------------

# Logical型:ベクトルでの動作 ---------------------------------

# Logical型:AND OR条件 -------------------------------------

######################################################

 

#Boolean/Logical========

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 and logical========================================

#ベクトルとlogical

 

#ベクトルも比較演算子で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]

 

#という感じでベクトルから取り出すことができます。

 

#まとめると、ロジカルのベクトルはベクトルから

#その要素を取り出すときに多用するものとなります

 

#<><=>=&|===============================================

#Logicalにもうしばらく付き合ってください。

 

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のエコシステム

#が非常に便利なので、この講義では

#あんまり出てきません。

 

####################################

# 正規表現1 -------------------------

####################################

 

#regex1===================================================

#さあ、filterへ!といきたいところでえすが、

#もう一山、Booleanが「しるし」になることを

#理解したあと、文字列に「しるし」をつける方法を学びましょう。

#正規表現というものですが、

#これは、多分、このコースでもかなりとっつきにくい

#部類に入ります。

 

#たとえば、次の文字列から、

#数字だけを抜き出したい場合にどのような方法がとれるでしょう?

 

vec <- c("HbA1c:9.2%","ALT:120UI","WBC:9.3x10^3")

 

#いままでにお伝えしたものでは無理です。

#ここから、このような、

#文字配列的に汚いデータから欲しいデータを抜き出す方法、

#正規表現を学びましょう。

 

#ちなみに、上記の問題は、

library(stringr)

str_extract(vec, "(?<=:)(\\d+\\.\\d+)|(?<=:)\\d+")

 

#で達成できます。

 

####################################

# 正規表現2 -------------------------

# 正規表現3 -------------------------

####################################

 

 

#regex2======================================================

#正規表現とは

#文字列をパターンでひっかける手法です。

 

#正規表現を完全にマスターすることは、

#本コースの目的ではありません。

#病院や医療現場でよくある問題を解決するための

#最低限をお伝えすることを目的としています。

#また、正規表現を利用しないで解決できる問題は

#可能な限りそっちを利用することが良いかもしれません。

 

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,"\\.+")

 

#################################################

# 正規表現4--------------------------------------

#################################################

 

#ここまでの知識で、

#最初の少数点のみ抜き出すということが実現できます。

 

#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)")

 

 

######################################################

# 正規表現5-----------------------------------------------

######################################################

 

#もうひといきです。

#次のような文字列から、欲しい数字を抜き出すにはどうするか?というところです。

 

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がだしています!

 

######################################################

# str_extract(文字列の抜き出し)とmutate(列の作成)-------------------

######################################################

 

#str_extract and 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)))"

  ))

#で抜き出すことができました!

 

######################################################

#filter(行の絞り込)============

######################################################

 

#filterの説明です。

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

 

test$umare > 1995

 

#このBooleanをfilterはtibbleの列に適応して、

#TRUEであるものを抜き出します。

 

test

 

test %>% filter(umare > 1995)

test %>% filter(height >= 175)

 

#実際にdiamondsにfilterを適応してみましょう

diamonds %>% filter(color == "E")

 

diamonds %>% filter(clarity=="SI1"|clarity=="SI2")

diamonds %>% filter(str_detect(clarity,"^SI\\d+$"))

 

diamonds$clarity %>% summary()

diamonds %>% filter(str_detect(clarity,"\\d"))

 

diamonds %>% filter(clarity != "IF")

 

########################################################################

#補足:全角から半角文字への変換、日本語の文字列の取り扱い ===================

########################################################################

 

install.packages("Nippon")

library(Nippon)

 

vec <- c("134.5ml投与","A薬5錠 分3")

 

#日本語のデータ分析を行う場合に、避けては通れない

#のが、全角の数字が出現している場合の問題です。

 

#正規表現は、数字はあたるはあたります

str_extract(vec,"\\d+")

#また、日本語も問題なく扱えます。

str_extract(vec,"薬")

vec

str_extract(vec,"(\\d+\\.\\d+)(?=ml)") #X

#これは、「.」が、全角であるために拾えません。

str_extract(vec,"(\\d+.\\d+)(?=ml)")

 

#また、

as.numeric("5")

#と文字列を数字に変更しようとしても、NAが帰ってくる

#ため、半角に早期に戻しておくほうが無難です。

 

#全角から半角はNipponパッケージを利用します。

"5" %>% as.numeric()

"5" %>% Nippon::zen2han() %>% as.numeric()

 

#必要に応じて、

#実施してみてください

 

#####################################################

# if_else(列内での条件分岐)1 -------------------------

# if_else(列内での条件分岐)2 -------------------------

#####################################################

 

#if_else case_when================================

dfif <- tibble(num =c(1:10))

 

dfif <- dfif %>% mutate(bool = num>5)

 

#if_elseはBooleanを判断して、

#TRUEとFALSEで処理をわける関数です。

 

if_else(FALSE, "trueです", "falseです")

 

 

if_else(c(TRUE,TRUE,FALSE), "trueだよ", "falseだよ")

 

if_else(c(TRUE,NA,FALSE), "trueだよ", "falseだよ", "NAだよ")

 

#これとmutateを組み合わせると、

 

dfif %>% 

  mutate(bool = num>4)

 

dfif %>% 

  mutate(bool = num>4) %>% 

  mutate(kekka = if_else(bool,

                         "4より大きいよ",

                         "4より小さいよ"))

 

#例では、一度boolというBooleanのベクトルを作っていますが、

dfif %>% 

  mutate(

    kekka = if_else(

      num < 3, "<3",">=3"

    )

  )

dfif <- dfif %>% select(-bool)

 

#でもOKです

 

dfif %>% 

  mutate(

    kekka = if_else(

      num < 3, "0",">=3",NA_character_

    )

  )

 

##################################################

# case_when(列内での複数条件分岐) -----------------

##################################################

 

#if_elseはTRUE/FALSEをかえす2条件のみですが、

#case_whenは複数条件で条件分岐ができます。

 

#<Booleanとなる条件式> ~ <返したい結果>

#を繰り返すことで好きな条件で結果を返せます。

 

dfif %>% 

  mutate(kekka = case_when(

    num == 1 ~ "one",

    num == 2 ~ "two",

    num == 3 ~ "three",

    TRUE ~ "else"

  ))

 

###################################################

#特殊加工:fill(空白を埋める) =======================

###################################################

 

#これまでは、mutate filter arrange等

#の列や行を操作する関数は、dplyrパッケージ、

 

#strではじまる正規表現を利用できる関数は、

#stringrパッケージ

 

#残りのfill separate gather spreadはtidyrパッケージの

#関数です。

 

#fill:

 

dffill <- tibble(name = c("a",NA,NA,"b",NA,NA),

                 type = rep(c("age","gender","bld"),2),

                 value = c("20","男","O","31","女","AB"))

 

#のように、人からみたら空白に見えるが

#意味のある行を埋めるのに使います。

 

dffill

 

dffill %>% fill(name)

 

dffill

dffill %>% fill(name, .direction = "up")

 

#.directionを設定することで上下に任意に埋めることができます。

 

######################################################

#特殊加工:separate(列を割る) ============================

######################################################

 

#練習問題を再度みてみましよう。

 

#任意の文字列で列を分割するseparate関数

#を利用してみましょう。

 

dft <- tibble(

  target3 = c(

    "ope:A 4.5hr 80ml",

    "ope:B 3hr 10ml",

    "ope:C 12.5hr 100ml"

  )

)

 

dft

 

#separate(data, col, into, sep)で利用します。

#dataはデータフレーム、colはコラム名。

#intoは、分割した後のコラム名、

#sepは分割のしるしとなる文字列

 

dft %>% 

  separate(col = target3, 

           into = c("OPE","HR","ML"),

           sep=" ")

 

#このように、スペース(\\s)で3つのコラムに分割され、

#もともとのtarget3は消えて、

#そのかわり、intoで指定した、OPE, HR, MLが出現しています。

 

dft %>% 

  separate(col = target3, 

           into = c("OPE", "HR", "ML"), 

           sep=" ", remove = FALSE)

 

#尚、remove=FALSEとすることで、

#削除せずに残すことも可能です。

 

#プチ課題:OPEコラムから、set_extractを使わずに

#オペ名を取り出してみましょう

 

dft %>% 

  separate(col = target3, 

           into = c("OPE", "HR", "ML"), 

           sep=" ") %>% 

  separate(col = OPE, 

           into = c("ope","opename"), 

           sep = ":") %>% 

  select(opename)

 

#str_extractを利用すると、

dft %>% 

  mutate(opename = str_extract(target3,"(?<=:)\\w+"))

 

#とより簡潔に書けますが、

#状況によっては、str_extractの正規表現が

#難しいケースもあり、

#そういう場合には、separateを利用することがよいと思います。

 

######################################################

#特殊加工:gather&spread 導入 ==================================

######################################################

 

#たて と よこ への変換

 

#ここまでは、行列へのそれぞれへの操作をみてきました。

#最後に、行列への同時操作をご紹介します

 

#横持データ

dfyoko <- tibble(

  tosi = c("札幌","東京","那覇"),

  `2018-04-01` = c("晴れ", "雨", "曇り"),

  `2018-04-02` = c("雨", "雨", "晴れ"),

  `2018-04-03` = c("晴れ", "雨", "曇り"),

  `2018-04-04` = c("晴れ", "雨", "雨")

)

 

 

View(dfyoko)

 

#このdfyokoは典型的な「横持データ」と呼ばれているものです。

#人には見やすいですが、

#tidyなデータではないということはお判りでしょうか?

 

#gather関数でtidyなデータにしてみましよう。

 

######################################################

# 特殊加工:gather&spread Rでの実践 ==========================================

######################################################

 

dfyoko <- tibble(

  tosi = c("札幌","東京","那覇"),

  `2018-04-01` = c("晴れ", "雨", "曇り"),

  `2018-04-02` = c("雨", "雨", "晴れ"),

  `2018-04-03` = c("晴れ", "雨", "曇り"),

  `2018-04-04` = c("晴れ", "雨", "雨")

)

 

dfyoko <- 

  dfyoko %>% 

  gather(-tosi, key=date_tenki, value = tenki)

 

 

#dfyokoをもとの横持ちデータにもどしてみます。

dfyoko <- dfyoko %>% 

  spread(key = date_tenki, value = tenki)

 

#注、dateを列名でつかわないほうがよい理由:

#スライドでは、dateをつかっていましたが、

#dateはもともと関数です。

#エラーが生じるので、

#基本的には列名やオブジェクトの名前に他の関数と同じ名前を

#付けることは避けてください。

 

#よくあるエラー

dfyoko_error <- 

  tibble(

    tosi = c(rep("札幌",4)),

    hiduke = c("2018-04-01","2018-04-02","2018-04-03","2018-04-01"),

    tenki = c("晴れ","雨","雨","雨")

)

 

dfyoko_error

 

dfyoko <- 

  dfyoko_error %>% 

  spread(key = hiduke, value = tenki)

#Error: Duplicate identifiers for rows (1, 4)

#このような表示がでるのは、なぜでしょうか?

#1行目と4行目のIdentifiers(札幌かつ2018-04-01)が

#Duplicate(重複)してますね。

#手でこのtibbleを横方向にしようとしても、

#2018年4月1日の札幌の天気はどっち(晴れ/雨)

#なんだと悩みます。

 

#こういったエラーの対処については、

#どのようにしてこの事態が発生したか、

#発生のメカニズムによって対処方法が違います。

#ここでは、その内容には踏み込みませんが

#欠損データの処理について成書を読んでみてください。

 

#尚、単純に同じデータが二回記録されているような

#ケースでは、

df_dup <- 

  tibble(

    tosi = c(rep("札幌",4)),

    hiduke = c("2018-04-01","2018-04-02","2018-04-03","2018-04-01"),

    tenki = c("雨","雨","雨","雨")

  )

 

df_dup

 

df_dup <- 

   df_dup %>% distinct()

 

#とすることにより、重複列が削除されますので、

df_dup <- 

  df_dup %>% distinct() %>% 

  spread(key = hiduke, value = tenki)

 

#とすることで横持にできます!

 

#################################################

#left_joinのRでの実践=============================

#################################################

 

#left_joinを説明する目的のために、dplyrに入っている、

#band_members と band_instrumentsで説明します。

library(tidyverse)

band_members

band_instruments

band_instruments2

 

left_join(band_members, band_instruments, 

          by = "name")

 

left_join(band_members, 

          band_instruments, by = c("name" = "name"))

 

band_members %>% 

  left_join(band_instruments, by = "name")

 

left_join(band_members, band_instruments2, by = "name")

#エラー!

band_instruments2

#->コラム名が、artist とplayerで、artistを利用したいので、

band_members %>% 

  left_join(band_instruments2, 

            by =c("name" = "artist"))

 

 

#他のJOIN====================================

#多くのケースでは、left_joinが使えれば、何とかなるので、

#例とその動作のみ簡単に説明します。

#尚、この例は、すべて、?left_joinでみられる

#ヘルプファイルからのコピーです。

 

# "Mutating" joins add variables to the LHS

band_members %>% 

  inner_join(band_instruments, by="name") #両方にあるものを残す。

band_members %>% 

  left_join(band_instruments) #左にあるものを残す

band_members %>% 

  right_join(band_instruments) #右にあるものを残す

band_members %>% 

  full_join(band_instruments) #どちらか片方にあるものを残す