── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.2 ✔ readr 2.1.4
✔ forcats 1.0.0 ✔ stringr 1.5.0
✔ ggplot2 3.4.2 ✔ tibble 3.2.1
✔ lubridate 1.9.2 ✔ tidyr 1.3.0
✔ purrr 1.0.1
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
それでは、separate関数の動きを見ていきましょう。
ヘルプをみると、col、into、sepだけでなく他にも色々なargumentがあります。簡単に動きを見ていきましょう
まずは、slideで解説したものからいきます。
dat <- tibble(tgt = c("glu:102 mg/dl","AST:41 IU/L",
"ALT:32 IU/L","GGT:33 IU/L"))
dat
# A tibble: 4 × 1
tgt
<chr>
1 glu:102 mg/dl
2 AST:41 IU/L
3 ALT:32 IU/L
4 GGT:33 IU/L
正規表現であれば
dat %>%
mutate(
name = str_extract(tgt,"^.+(?=:)"),
value = str_extract(tgt,"(?<=:)\\d+"),
unit = str_extract(tgt,"(?<=\\s).+$"),
)
# A tibble: 4 × 4
tgt name value unit
<chr> <chr> <chr> <chr>
1 glu:102 mg/dl glu 102 mg/dl
2 AST:41 IU/L AST 41 IU/L
3 ALT:32 IU/L ALT 32 IU/L
4 GGT:33 IU/L GGT 33 IU/L
こんな感じで抜き出せましたね?
separateで書くと、
dat %>%
separate(tgt, into=c("name","value","unit"),sep=":|\\s")
# A tibble: 4 × 3
name value unit
<chr> <chr> <chr>
1 glu 102 mg/dl
2 AST 41 IU/L
3 ALT 32 IU/L
4 GGT 33 IU/L
こんな感じです。
str_extractと比べてだいぶ楽ではありませんか?
argumentの設定も見ていきましょう。
remove=FALSEに変更することで、
dat %>%
separate(tgt, into=c("name","value","unit"),sep=":|\\s")
# A tibble: 4 × 3
name value unit
<chr> <chr> <chr>
1 glu 102 mg/dl
2 AST 41 IU/L
3 ALT 32 IU/L
4 GGT 33 IU/L
dat %>%
separate(tgt, into=c("name","value","unit"),sep=":|\\s",
remove=FALSE)
# A tibble: 4 × 4
tgt name value unit
<chr> <chr> <chr> <chr>
1 glu:102 mg/dl glu 102 mg/dl
2 AST:41 IU/L AST 41 IU/L
3 ALT:32 IU/L ALT 32 IU/L
4 GGT:33 IU/L GGT 33 IU/L
元の列を残したまま処理することが可能です。
convert=TRUEとすると、
dat %>%
separate(tgt, into=c("name","value","unit"),sep=":|\\s")
# A tibble: 4 × 3
name value unit
<chr> <chr> <chr>
1 glu 102 mg/dl
2 AST 41 IU/L
3 ALT 32 IU/L
4 GGT 33 IU/L
dat %>%
separate(tgt, into=c("name","value","unit"),sep=":|\\s",
remove=FALSE, convert=TRUE)
# A tibble: 4 × 4
tgt name value unit
<chr> <chr> <int> <chr>
1 glu:102 mg/dl glu 102 mg/dl
2 AST:41 IU/L AST 41 IU/L
3 ALT:32 IU/L ALT 32 IU/L
4 GGT:33 IU/L GGT 33 IU/L
分けた後の型変換(数値型等)も自動的にしてくれます。
extraは要素が多い時の動作を指定します。
dat2 <- tibble(
tgt = c("glu:102 mg/dl 注意:食後",
"AST:41 IU/L",
"ALT:32 IU/L",
"GGT:33 IU/L")
)
dat2 %>%
separate(tgt, into=c("name","value","unit"),sep=":|\\s",
remove=FALSE, convert=TRUE)
Warning: Expected 3 pieces. Additional pieces discarded in 1 rows [1].
# A tibble: 4 × 4
tgt name value unit
<chr> <chr> <int> <chr>
1 glu:102 mg/dl 注意:食後 glu 102 mg/dl
2 AST:41 IU/L AST 41 IU/L
3 ALT:32 IU/L ALT 32 IU/L
4 GGT:33 IU/L GGT 33 IU/L
1行目の要素が多すぎるデータをseparateしてみると、このように、警告(warning)してくれます。この動作、extraのargumentでコントロールできて、デフォルトは、warnです。
warnだと警告とともに、余分な要素は無視されます。
dat2 %>%
separate(tgt, into=c("name","value","unit"),sep=":|\\s",
remove=FALSE, convert=TRUE, extra="warn")
Warning: Expected 3 pieces. Additional pieces discarded in 1 rows [1].
# A tibble: 4 × 4
tgt name value unit
<chr> <chr> <int> <chr>
1 glu:102 mg/dl 注意:食後 glu 102 mg/dl
2 AST:41 IU/L AST 41 IU/L
3 ALT:32 IU/L ALT 32 IU/L
4 GGT:33 IU/L GGT 33 IU/L
dropにしておくと、警告はなくて、余分な要素が無視されます
dat2 %>%
separate(tgt, into=c("name","value","unit"),sep=":|\\s",
remove=FALSE, convert=TRUE, extra="drop")
# A tibble: 4 × 4
tgt name value unit
<chr> <chr> <int> <chr>
1 glu:102 mg/dl 注意:食後 glu 102 mg/dl
2 AST:41 IU/L AST 41 IU/L
3 ALT:32 IU/L ALT 32 IU/L
4 GGT:33 IU/L GGT 33 IU/L
fillは、intoで指定した列に「分割することをやめて」収めてくれます。
dat2 %>%
separate(tgt, into=c("name","value","unit"),sep=":|\\s",
remove=FALSE, convert=TRUE, extra="merge")
# A tibble: 4 × 4
tgt name value unit
<chr> <chr> <int> <chr>
1 glu:102 mg/dl 注意:食後 glu 102 mg/dl 注意:食後
2 AST:41 IU/L AST 41 IU/L
3 ALT:32 IU/L ALT 32 IU/L
4 GGT:33 IU/L GGT 33 IU/L
fillは要素が少ない場合の動作を指定します
dat3 <- tibble(
tgt = c("glu:-",
"AST:41 IU/L",
"ALT:32 IU/L",
"GGT:未")
)
fillに与えられるのは、warn right leftの3種類でデフォルトはwarnです。
dat3 %>%
separate(tgt, into=c("name","value","unit"),sep=":|\\s",
remove=FALSE, convert=TRUE, fill="warn")
Warning: Expected 3 pieces. Missing pieces filled with `NA` in 2 rows [1, 4].
# A tibble: 4 × 4
tgt name value unit
<chr> <chr> <chr> <chr>
1 glu:- glu - <NA>
2 AST:41 IU/L AST 41 IU/L
3 ALT:32 IU/L ALT 32 IU/L
4 GGT:未 GGT 未 <NA>
dat3 %>%
separate(tgt, into=c("name","value","unit"),sep=":|\\s",
remove=FALSE, convert=TRUE, fill="right")
# A tibble: 4 × 4
tgt name value unit
<chr> <chr> <chr> <chr>
1 glu:- glu - <NA>
2 AST:41 IU/L AST 41 IU/L
3 ALT:32 IU/L ALT 32 IU/L
4 GGT:未 GGT 未 <NA>
dat3 %>%
separate(tgt, into=c("name","value","unit"),sep=":|\\s",
remove=FALSE, convert=TRUE, fill="left")
# A tibble: 4 × 4
tgt name value unit
<chr> <chr> <chr> <chr>
1 glu:- <NA> glu -
2 AST:41 IU/L AST 41 IU/L
3 ALT:32 IU/L ALT 32 IU/L
4 GGT:未 <NA> GGT 未
ここの設定、要素が不足しているときに右に詰めるか左に詰めるかを指定するだけです。
sepですが、正規表現(文字列)だけでなく、数字で区切る位置を指定することも可能です。
例えば、検査名検査結果1回目2回目3回目を、 ken000100020003
の様に記載されたデータがあった場合に、正規表現で区切り位置を示すのは難しいので、 ken000100020003 123456789012345678 | | |
3 7 11
3,7,11文字目で区切ることにしましょう(検査名は必ずアルファベット3文字で表されるように、データの種類、文字列の位置で固定されているデータとします。)
dat4 <- tibble(
tgt = c("glu010000890095",
"ast003000400050",
"alt002000300040")
)
dat4 %>%
separate(col=tgt,into=c("name","v1","v2","v3"),sep=c(3,7,11))
# A tibble: 3 × 4
name v1 v2 v3
<chr> <chr> <chr> <chr>
1 glu 0100 0089 0095
2 ast 0030 0040 0050
3 alt 0020 0030 0040
いかがでしょうか? 文字列の位置でも簡単に切り分けることができました。
このseparate関数、かなり便利な関数ですので是非使い方をマスターしておいてください。