为什么我不能使用 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
$
- 字符串结尾。
第一次在这里提问,如有遗漏请见谅。我一直在查看现有答案,但找不到任何专门解决此问题的答案。
我正在尝试使用 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
$
- 字符串结尾。