ここではdata/stringr.xlsxファイルを利用します
練習問題1
インポートしてください
練習問題2-1
target3をname、hr、mlの3つの列にseparateを使ってわけてください。
練習問題2-1
target3をname、hr、mlの3つの列にextractを使ってわけてください。
練習問題3-1
target2をname,value,unitの3つの列にseparateを使って分けてください。
練習問題3-2
target2をname,value,unitの3つの列にextractを使って分けてください。
練習問題4-1
target1をname,ml,unitの3つの列にseparateを使って分けてください。
練習問題4-2
target1をname,ml,unitの3つの列にextractを使って分けてください。
解答です。
── 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
練習問題1
インポートしてください
dat <- read_excel("data/stringr.xlsx")
dat
# A tibble: 6 × 3
target1 target2 target3
<chr> <chr> <chr>
1 abc:500ml 1unit AST 50IU, ope:A 4.5hr 8Oml
2 def 250ml 4units HbA1c 5.0% ope:B 3hr 10ml
3 ghi 100ml 5units BMI 23.1kg/m^2 ope:C 12.5hr 1OOml
4 jkl 100ml 6units AST: 60IU ope:D 4.5hr 180ml
5 jkl 100ml 9units HbA1c 5.0% ope:E 3hr 120ml
6 abc 100ml 20units BMI 18.1kg/m^2 ope:F 12.5hr 1OOml
練習問題2-1
target3をname、hr、mlの3つの列にseparateを使ってわけてください。
dat %>%
select(target3) %>%
separate(col = target3,
into = c("ope","name","hr","ml"),
sep=":|\\s+", remove=FALSE) %>%
select(-ope)
# A tibble: 6 × 4
target3 name hr ml
<chr> <chr> <chr> <chr>
1 ope:A 4.5hr 8Oml A 4.5hr 8Oml
2 ope:B 3hr 10ml B 3hr 10ml
3 ope:C 12.5hr 1OOml C 12.5hr 1OOml
4 ope:D 4.5hr 180ml D 4.5hr 180ml
5 ope:E 3hr 120ml E 3hr 120ml
6 ope:F 12.5hr 1OOml F 12.5hr 1OOml
この方法だと、hrやml等、余計な文字列がくっついているので、str_removeなどで除去してあげる必要がありますね。
練習問題2-1
target3をname、hr、mlの3つの列にextractを使ってわけてください。
dat %>%
select(target3) %>%
extract(target3, c("name","hr","ml"),
regex="ope:(.+) (.+)hr (.+)ml",
remove = FALSE)
# A tibble: 6 × 4
target3 name hr ml
<chr> <chr> <chr> <chr>
1 ope:A 4.5hr 8Oml A 4.5 8O
2 ope:B 3hr 10ml B 3 10
3 ope:C 12.5hr 1OOml C 12.5 1OO
4 ope:D 4.5hr 180ml D 4.5 180
5 ope:E 3hr 120ml E 3 120
6 ope:F 12.5hr 1OOml F 12.5 1OO
いかがでしょうか?extractを利用するとseparateよりも正規表現を記載する手間はありますが、より細かく分けることができます。
練習問題3-1
target2をname,value,unitの3つの列にseparateを使って分けてください。
dat %>%
select(target2) %>%
separate(target2,c("name","value","unit"),
sep = ":\\s+|:|\\s+") %>%
mutate(
unit = str_remove(value,"\\d+\\.\\d+|\\d+"),
value = str_extract(value,"\\d+\\.\\d+|\\d+")
)
Warning: Expected 3 pieces. Missing pieces filled with `NA` in 6 rows [1, 2, 3, 4, 5,
6].
# A tibble: 6 × 3
name value unit
<chr> <chr> <chr>
1 AST 50 IU,
2 HbA1c 5.0 %
3 BMI 23.1 kg/m^2
4 AST 60 IU
5 HbA1c 5.0 %
6 BMI 18.1 kg/m^2
練習問題3-2
target2をname,value,unitの3つの列にextractを使って分けてください。
dat %>%
select(target2) %>%
extract(target2,c("name","value","unit"),
regex = "(.+)[:\\s]+(\\d+\\.\\d+|\\d+)(.+)$")
# A tibble: 6 × 3
name value unit
<chr> <chr> <chr>
1 AST 50 IU,
2 HbA1c 5.0 %
3 BMI 23.1 kg/m^2
4 AST: 60 IU
5 HbA1c 5.0 %
6 BMI 18.1 kg/m^2
いかがでしょうか?
extractの方がより複雑な形に一度で対応できますね?
練習問題4-1
target1をname,ml,unitの3つの列にseparateを使って分けてください。
dat %>%
select(target1) %>%
separate(target1,c("name","ml","unit"),
sep=":|\\s+") %>%
mutate(
ml = str_remove(ml,"ml"),
unit = str_remove(unit,"unit(s|)")
)
# A tibble: 6 × 3
name ml unit
<chr> <chr> <chr>
1 abc 500 1
2 def 250 4
3 ghi 100 5
4 jkl 100 6
5 jkl 100 9
6 abc 100 20
練習問題4-2
target1をname,ml,unitの3つの列にextractを使って分けてください。
dat %>%
select(target1) %>%
extract(target1,c("name","ml","unit"),
regex="(.+)[:\\s]+(\\d+)ml (\\d+)unit") %>%
mutate(name = str_trim(name))
# A tibble: 6 × 3
name ml unit
<chr> <chr> <chr>
1 abc 500 1
2 def 250 4
3 ghi 100 5
4 jkl 100 6
5 jkl 100 9
6 abc 100 20
以上、いかがでしょうか?
正規表現を考えて抜き出す場合よりもseparateやextractを利用する方が簡単な場合もあるので、どの関数を利用するか、お手元のデータの形をみて、考えてみてください。