为什么我不能使用 tidyr extract 和 regex 拆分此列?

Why can't I split this column using tidyr extract and regex?

第一次在这里提问,如有遗漏请见谅。我一直在查看现有答案,但找不到任何专门解决此问题的答案。

我正在尝试使用 tidyr 包的提取功能将不一致的字符串拆分为两个变量。

使用库调用表示我的数据:

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)

我想提取到两个单独变量中的字符串是 'duration' 列中的数字。将它们拆分为标题为 'hours' 和 'minutes' 的列,结果是:

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))")

所有这一切都产生了两列,正确命名为 'hours' 和 'minutes' 但错误地填充了 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
  • $ - 字符串结尾。