{tidyr} 中的提取函数有问题

Having issue with extract function in {tidyr}

我有一个看起来像这样的数据框。我将其命名为“df_raw”。

"HRHHID\t15\tHOUSEHOLD IDENTIFIER\t(Part 1)\t1- 15"
"HRMONTH\t2\tMONTH OF INTERVIEW\t16-17"
"HRYEAR4\t4\tYEAR OF INTERVIEW\t\t18-21"
"HURESPLI\t2\tLINE NUMBER OF THE RESPONDENT\tCURRENT\t22 - 23" "FILLER\t2\t\t27 - 28" ...

我正在尝试提取末尾的数字范围,例如 1-15、16-17、18-21 等等。 我在正则表达式测试器 (https://regexr.com/63nl1) 上准备了我的正则表达式语法,它似乎以我想要的为目标。

正则表达式:\d+(\s?)-(\s?)\d+$

然后我转到 R 并尝试在 tidyr 中使用提取函数(这是我第一次使用它),我得到错误:“错误:regex 应该定义 1 个组;找到."

df_raw %>% 
extract(col = value, into = "", regex = "\d+(\s?)-(\s?)\d+$")

任何人都可以帮助我了解如何对我的正则表达式进行分组以便提取功能起作用吗?

非常感谢, 大卫

我们可以使用 trimws 执行此操作,方法是指定 whitespace 删除所有内容,直到 \t

library(dplyr)
library(stringr)
df_raw %>%
      mutate(new = str_remove_all(trimws(value, whitespace = ".*\t"), "\s+"))

-输出

# A tibble: 5 x 2
  value                                                          new  
  <chr>                                                          <chr>
1 "HRHHID\t15\tHOUSEHOLD IDENTIFIER\t(Part 1)\t1- 15"            1-15 
2 "HRMONTH\t2\tMONTH OF INTERVIEW\t16-17"                        16-17
3 "HRYEAR4\t4\tYEAR OF INTERVIEW\t\t18-21"                       18-21
4 "HURESPLI\t2\tLINE NUMBER OF THE RESPONDENT\tCURRENT\t22 - 23" 22-23
5 "FILLER\t2\t\t27 - 28"                                         27-28

或者使用 extract,OP 的 post 中的代码显示了多个捕获组,而我们只想提取到一个列中。在这种情况下,只需获取数字 (\d+) 后跟任何空格 (\s*)、-,然后是任何空格和数字,将其用 (...) 包裹起来作为捕获在字符串

的末尾 ($) 分组
library(tidyr)
df_raw %>% 
    extract(col = value, into = "new",  "(\d+\s*-\s*\d+)$")
# A tibble: 5 x 1
  new    
  <chr>  
1 1- 15  
2 16-17  
3 18-21  
4 22 - 23
5 27 - 28

或仅使用 base R

trimws(df_raw$value, whitespace = ".*\t")
[1] "1- 15"   "16-17"   "18-21"   "22 - 23" "27 - 28"

数据

df_raw <- structure(list(value = c("HRHHID\t15\tHOUSEHOLD IDENTIFIER\t(Part 1)\t1- 15", 
"HRMONTH\t2\tMONTH OF INTERVIEW\t16-17", "HRYEAR4\t4\tYEAR OF INTERVIEW\t\t18-21", 
"HURESPLI\t2\tLINE NUMBER OF THE RESPONDENT\tCURRENT\t22 - 23", 
"FILLER\t2\t\t27 - 28")), row.names = c(NA, -5L), class = c("tbl_df", 
"tbl", "data.frame"))

我认为您遇到了问题,因为您的正则表达式必须匹配数字之间的空格("(\s?)-(\s?)",但您的数据显示的空格不一致。也许您应该匹配“none 或更多”空格, "\s*",没有括号或 ? 符号。 您也可以使用 tidyr::separate():

library(tidyr)

df_raw %>% separate(value, sep="\d+\s*-\s*\d+$")

如果要使新列在空格方面保持一致,可以使用 str_extract()mutate 新列,然后将其通过管道传输到某些转换

df_raw %>% mutate(new_column = str_extract(value, "\d+\s*-\s*\d+$") %>%
                  str_replace("\s*-\s*", " - ")

将字符串拆分为 \t

然后你得到一个列表

然后unnest列表

组并保留组中的最后一个:

library(dplyr)
df <- df_raw %>% 
    mutate(x = strsplit(value, "\t")) %>% 
    unnest(cols = c(x)) %>% 
    group_by(value) %>% 
    slice(n())

输出:

  value                                                          x      
  <chr>                                                          <chr>  
1 "FILLER\t2\t\t27 - 28"                                         27 - 28
2 "HRHHID\t15\tHOUSEHOLD IDENTIFIER\t(Part 1)\t1- 15"            1- 15  
3 "HRMONTH\t2\tMONTH OF INTERVIEW\t16-17"                        16-17  
4 "HRYEAR4\t4\tYEAR OF INTERVIEW\t\t18-21"                       18-21  
5 "HURESPLI\t2\tLINE NUMBER OF THE RESPONDENT\tCURRENT\t22 - 23" 22 - 23