R-Regex在不同格式的关键字之前提取数字



我需要从字符串中提取数字,然后再提取它们各自的单位。不幸的是,输入有时会有所不同,这给我带来了麻烦。

样本数据:

df <- data.frame(id = c(1, 2, 3, 4),
targets = c("1800 kcal 75 g", "2000kcal 80g", "1900 kcal,87g", "2035kcal,80g"))
> df
id        targets
1  1 1800 kcal 75 g
2  2   2000kcal 80g
3  3  1900 kcal,87g
4  4   2035kcal,80g

期望输出:

df <- data.frame(id = c(1, 2, 3, 4),
targets = c("1800 kcal 75 g", "2000kcal 80g", "1900 kcal,87g", "2035kcal,80g"),
kcal_target = c("1800", "2000", "1900", "2035"),
protein_target = c("75", "80", "87", "80"))
> df
id        targets kcal_target protein_target
1  1 1800 kcal 75 g        1800             75
2  2   2000kcal 80g        2000             80
3  3  1900 kcal,87g        1900             87
4  4   2035kcal,80g        2035             80

我已经做到了这一点,但它在数字和单位关键字之间用空格分隔,在数字关键字后面用逗号分隔。

df <- df %>%
mutate(calorie_target = str_extract_all(targets, regex("\d+(?=kcal)|\d+(?=kcal,)"))) %>%
mutate(protein_target = str_extract_all(targets,  regex("\d+(?=g)")))
> df
id        targets calorie_target protein_target
1  1 1800 kcal 75 g                              
2  2   2000kcal 80g           2000             80
3  3  1900 kcal,87g                            87
4  4   2035kcal,80g           2035             80

编辑:删除了代码的一部分我不想捕捉

strcapture:的基本R

strcapture("(\d+)\D+(\d+)", df$targets, list(calorie=0L, protein=0L))
#   calorie protein
# 1    1800      75
# 2    2000      80
# 3    1900      87
# 4    2035      80

您可以将此cbind复制到原始:

cbind(df, strcapture("(\d+)\D+(\d+)", df$targets, list(calorie=0L, protein=0L)))
#   id        targets calorie protein
# 1  1 1800 kcal 75 g    1800      75
# 2  2   2000kcal 80g    2000      80
# 3  3  1900 kcal,87g    1900      87
# 4  4   2035kcal,80g    2035      80

如果你想把它放在dplyr管道中,那么

library(dplyr)
df %>%
bind_cols(strcapture("(\d+)\D+(\d+)", .$targets, list(calorie=0L, protein=0L)))
#   id        targets calorie protein
# 1  1 1800 kcal 75 g    1800      75
# 2  2   2000kcal 80g    2000      80
# 3  3  1900 kcal,87g    1900      87
# 4  4   2035kcal,80g    2035      80

请注意,strcapture在引擎盖下使用regexecregmatches,因此这与@ThomasIsCoding在这方面的回答类似。

对于正则表达式,

  • \d任意数字(包括unicode(;这与[0-9]类似,但也包括其他数字(请参见https://stackoverflow.com/a/16621778/3358272)
  • \D任意非数字
  • +一个或多个(前一个字符/类的(

如果你需要的话,这是一个很好的参考https://stackoverflow.com/a/22944075/3358272.

以下是使用regmatches+transposedata.table选项

setDT(df)[, setNames(transpose(regmatches(targets, gregexpr("\d+", targets))), c("kcal_target", "protein_target")), id]

它给出

id kcal_target protein_target
1:  1        1800             75
2:  2        2000             80
3:  3        1900             87
4:  4        2035             80

最新更新