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

标签 r regex tidyr tidyselect

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

我确实研究了几个regex问题; this onethis one ,以及 regex101.com 。受 this question 的启发,我尝试使用 regexstarts_with()ends_with() 来规避 matches() ,但没有成功。

我在这里提问,希望有人能指出我哪里出错了,我可以解决它,最好使用 中的选择助手

我需要选择 2 regex -一组到最后一个 . ,一组由最后一个 . 之后的内容组成,我在下面做了两个例子,一个是我的代码工作的地方,另一个是我被卡住的地方。

首先是正在运行的示例,

# 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() 等)的简单解决方案 this question 将不胜感激。

最佳答案

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

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

关于正则表达式(使用 tidyr 收集多组列),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48853192/

相关文章:

r - 查找相同组的数量

r - 带编号的点标签加上散点图中的图例

r - 具有交互式 x 轴范围的 ggvis 折线图

r - 分成列,将连续的分隔符视为一个

r - 在不同环境中调用时,部分粘合功能不起作用

regex - 如何在swift中使用正则表达式?

javascript - 如何查找正则表达式的部分 - 整数?

php - 穿梭在每根弦之间

r - 将百万/十亿缩写变为实际数字? IE。 5.12M -> 5,120,000

r - 使用多个分隔符将一列拆分为两列时,将多余的内容合并到左侧