133  練習問題

ここでは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を使って分けてください。

解答です。

library(tidyverse)
── 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
library(readxl)

練習問題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を利用する方が簡単な場合もあるので、どの関数を利用するか、お手元のデータの形をみて、考えてみてください。