第一次在这里提问,如有遗漏,敬请谅解。我一直在查看现有答案,但找不到专门解决此问题的答案。
我正在尝试使用 tidyr 包的 extract 函数将不一致的字符串拆分为两个变量。
通过库调用表示我的数据:
library(tidyverse)
date <- c("2017-09-30", "2017-10-02", "2017-10-05", "2017-10-07")
exercise <- c("gym", "run", "gym", "walk")
duration <- c("1h 31m", "45m", "1h 42m", "2h")
raw_data <- tibble(date, exercise, duration)
我想要提取到两个单独变量中的字符串是“持续时间”列中的数字。将它们分成标题为“小时”和“分钟”的列,结果如下:
date <- c("2017-09-30", "2017-10-02", "2017-10-05", "2017-10-07")
exercise <- c("gym", "run", "gym", "walk")
hours <- c("1", "NA", "1", "2")
minutes <- c("31", "45", "42", "NA")
raw_data <- tibble(date, exercise, hours, minutes)
...然后我计划使用 mutate 调用来存储以分钟为单位的整个持续时间(例如 c("91", "45", "102", "120")
到目前为止我的尝试:
clean_data <- raw_data %>%
extract(duration,
c("hours", "minutes"),
"([\\d]+(?=h)) \\s ([\\d]+(?=m))")
这只是生成两列,正确命名为“小时”和“分钟”,但错误地填充了 NA。
我不熟悉正则表达式,所以我认为问题出在某个地方,我尝试了以下方法,它确实提取了正确的值:
str_extract_all(raw_data$duration, "[\\d]+(?=h)")
str_extract_all(raw_data$duration, "[\\d]+(?=m)")
所以我猜我的错误要么与空格有关,但我已经用尽了我能想到的所有选项;或者与初始字符串的不一致有关。我发现的所有现有堆栈溢出答案都具有一致的字符串。
有人能看出我哪里出错了吗?提前致谢!
最佳答案
您使用的环视是非消耗模式,而您需要使用消耗模式来让正则表达式引擎在几小时后的几分钟内到达。
您可以使用以下方法解决问题
pattern <- "^(?!$)(?:(\\d+)h\\h*)?(?:(\\d+)m)?$"
clean_data <- raw_data %>%
extract(duration,c("hours", "minutes"), pattern)
clean_data
# A tibble: 4 x 4
# date exercise hours minutes
# <chr> <chr> <chr> <chr>
# 1 2017-09-30 gym "1" "31"
# 2 2017-10-02 run "" "45"
# 3 2017-10-05 gym "1" "42"
# 4 2017-10-07 walk "2" ""
请参阅regex demo 。 详细信息:
^
- 字符串开始(?!$)
- 字符串开始位置不允许有字符串结尾(?:(\d+)h\h*)?
- 可选序列(\d+)
- 第 1 组:一位或多位数字h\h*
-h
和零个或多个水平空白
(?:(\d+)m)?
- 一个或多个数字的可选序列(第 2 组),然后是m
$
- 字符串结尾。
关于r - 为什么我不能使用 tidyr extract 和 regex 拆分此列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67972160/