正则表达式(用tidyr收集多组列)

时间:2018-02-18 15:15:29

标签: r regex tidyr tidyselect

hadley's nifty gather approach in this answer的启发我试图将gather()spread()与正则表达式regex结合使用,但我似乎得到了regex上的错误。

我确实研究了几个regex个问题; this onethis one以及regex101.com。我尝试使用regexstarts_with()ends_with()启发matches()来绕过regex,但没有运气。

我在这里问,希望有人可以证明我弄错了,我可以解决它,最好是使用this question中的选择助手

我需要选择2 . - 一组到最后一个.,一组由最后一个# install.packages(c("tidyverse"), dependencies = TRUE) require(tidyverse) 组成,我在下面做了两个例子,一个是我的代码工作和我被卡住的地方。

首先是正在运作的例子,

myData1 <- tibble(
  id = 1:10,
  Wage.1997.1 = c(NA, 32:38, NA, NA),
  Wage.1997.2 = c(NA, 12:18, NA, NA),
  Wage.1998.1 = c(NA, 42:48, NA, NA),
  Wage.1998.2 = c(NA, 2:8, NA, NA),  
  Wage.1998.3 =  c(NA, 42:48, NA, NA),    
  Job.Type.1997.1 = NA,
  Job.Type.1997.2 = c(NA, rep(c('A', 'B'), 4), NA),
  Job.Type.1998.1 = c(NA, rep(c('A', 'B'), 4), NA),
  Job.Type.1998.2 = c(NA, rep(c('A', 'B'), 4), NA)  
)

第一个工作的数据集如下所示,

gather()

这就是我myData1 %>% gather(key, value, -id) %>% extract(col = key, into = c("variable", "id.job"), regex = "(.*?\\..*?)\\.(.)$") %>% spread(variable, value) #> # A tibble: 30 x 6 #> id id.job Job.Type.1997 Job.Type.1998 Wage.1997 Wage.1998 #> <int> <chr> <chr> <chr> <chr> <chr> #> 1 1 1 <NA> <NA> <NA> <NA> #> 2 1 2 <NA> <NA> <NA> <NA> #> 3 1 3 <NA> <NA> <NA> <NA> #> 4 2 1 <NA> A 32 42 #> 5 2 2 A A 12 2 #> 6 2 3 <NA> <NA> <NA> 42 #> 7 3 1 <NA> B 33 43 #> 8 3 2 B B 13 3 #> 9 3 3 <NA> <NA> <NA> 43 #> 10 4 1 <NA> A 34 44 #> # ... with 20 more rows 的方式,

regex

它有效,我怀疑我用myData2 <- tibble( id = 1:10, Wage.1997.1 = c(NA, 32:38, NA, NA), Wage.1997.12 = c(NA, 12:18, NA, NA), Wage.1998.1 = c(NA, 42:48, NA, NA), Wage.1998.12 = c(NA, 2:8, NA, NA), Wage.1998.13 = c(NA, 42:48, NA, NA), Job.Type.1997.1 = NA, Job.Type.1997.12 = c(NA, rep(c('A', 'B'), 4), NA), Job.Type.1998.1 = c(NA, rep(c('A', 'B'), 4), NA), Job.Type.1998.12 = c(NA, rep(c('A', 'B'), 4), NA) ) 过度了,但它确实有效。但是,我的真实数据最后可以有一个或两个摘要,即

第二个数据,我卡住了,

(0[0-1]|1[0-9])$

现在,我在第二组中使用\d{1}|\d{2},我也尝试了myData2 %>% gather(key, value, -id) %>% extract(col = key, into = c("variable", "id.job"), regex = "(.*?\\..*?)\\.(0[0-1]|1[0-9])$") %>% spread(variable, value) 之类的内容,但这样做也不起作用。

#> # A tibble: 30 x 6
#>       id id.job Job.Type.1997 Job.Type.1998 Wage.1997 Wage.1998
#>    <int> <chr>  <chr>         <chr>         <chr>     <chr>    
#>  1     1 1      <NA>          <NA>          <NA>      <NA>     
#>  2     1 12     <NA>          <NA>          <NA>      <NA>     
#>  3     1 13     <NA>          <NA>          <NA>      <NA>     
#>  4     2 1      <NA>          A             32        42       
#>  5     2 12     A             A             12        2        
#>  6     2 13     <NA>          <NA>          <NA>      42       
#>  7     3 1      <NA>          B             33        43       
#>  8     3 12     B             B             13        3        
#>  9     3 13     <NA>          <NA>          <NA>      43       
#> 10     4 1      <NA>          A             34        44       
#> # ... with 20 more rows

预期的输出将是这样的,

starts_with()

使用选择帮助(例如ends_with()matches()dry-validation等简单解决方案,我们将不胜感激。< / p>

1 个答案:

答案 0 :(得分:3)

我们可以更改regex中的extract以匹配字符,并从字符串的开头((.*))后跟一个点捕获为组(^)( \\.)和一个或多个不是作为一个组(([^.]+))捕获的点的字符,直到字符串的结尾($

myData2 %>%
    gather(key, value, -id)  %>% 
    extract(col = key, into = c("variable", "id.job"), "^(.*)\\.([^.]+)$") %>%
    spread(variable, value)
# A tibble: 30 x 6
#      id id.job Job.Type.1997 Job.Type.1998 Wage.1997 Wage.1998
# * <int> <chr>  <chr>         <chr>         <chr>     <chr>    
# 1     1 1      <NA>          <NA>          <NA>      <NA>     
# 2     1 12     <NA>          <NA>          <NA>      <NA>     
# 3     1 13     <NA>          <NA>          <NA>      <NA>     
# 4     2 1      <NA>          A             32        42       
# 5     2 12     A             A             12        2        
# 6     2 13     <NA>          <NA>          <NA>      42       
# 7     3 1      <NA>          B             33        43       
# 8     3 12     B             B             13        3        
# 9     3 13     <NA>          <NA>          <NA>      43       
#10     4 1      <NA>          A             34        44       
# ... with 20 more rows