从 data.table R 中的字符变量中提取数值和字符值

Extract numeric and character values from a character variable in data.table R

我有以下data.table

df <- data.table(id=c(1,2,3,4),
                 medication=c("Abc de 3 MG", "Afg frt re 4 MG/ML","Agh","Aj yr 5 MG"))

id         medication
1:  1        Abc de 3 MG
2:  2 Afg frt re 4 MG/ML
3:  3                Agh
4:  4         Aj yr 5 MG

我想从药物中提取剂量,并创建一个名为 doses

的列
id medication   doses
1:  1     Abc de    3 MG
2:  2 Afg frt re 4 MG/ML
3:  3        Agh    <NA>
4:  4      Aj yr    5 MG

它应该包含数字和单位。并非每种药物都有编号和单位,应包括为 NA

我查看了 tidyverse extract 函数,但找不到可以提取 numericcharacter 值的内容。 我正在对大型数据集使用 data.table。省时的功能很棒。

也许你可以像下面那样尝试strsplit

df[-1] <- do.call(rbind,lapply(strsplit(df$medication,"(?<=[A-Za-z])\s(?=[0-9])",perl = TRUE),`length<-`,2))

这给出了

> df
  id medication.1 medication.2
1  1       Abc de         3 MG
2  2   Afg frt re      4 MG/ML
3  3          Agh         <NA>
4  4        Aj yr         5 MG

在第一个数字之前插入一个 @(或任何其他不在您的列中的字符),然后使用它将列分成两列:

df[, c("medication", "doses") := tstrsplit(sub("([0-9])", "@\1", medication), "@")]
df

#    id  medication   doses
# 1:  1     Abc de     3 MG
# 2:  2 Afg frt re  4 MG/ML
# 3:  3         Agh    <NA>
# 4:  4      Aj yr     5 MG

编辑

更干净的解决方案是使用稍微更高级的正则表达式(正前瞻),只需要记住 perl = TRUE:

df[, c("medication", "doses") := tstrsplit(medication, ".(?=[0-9])", perl = TRUE)]

extract 来自 tidyr

的选项
library(tidyr)
extract(df, medication, into = c('medication', 'doses'), '(.*)\s+(\d+\s+\D+)$')
#   id medication   doses
#1:  1     Abc de    3 MG
#2:  2 Afg frt re 4 MG/ML
#3:  3       <NA>    <NA>
#4:  4      Aj yr    5 MG

虽然不是这个方法data.table,但是你可以考虑一下

library(tidyr)
df %>% 
  separate(medication, into = c("medication", "doses"), sep = "(?=\d)")
# id  medication   doses
# 1  1     Abc de     3 MG
# 2  2 Afg frt re  4 MG/ML
# 3  3         Agh    <NA>
# 4  4      Aj yr     5 MG