如何使用stringr和regex转换字符串(更改,保留,提取)有一些例外?

时间:2016-11-10 05:01:31

标签: r regex stringr

嘿,我有一个数据集,我手工挑选了以下7个条目作为例子:

mydf <- data.frame(transmission = c('Auto(L3)','Auto(L4)','Auto (S4)','Automatic (6-spd)','Automatic (L3)',
'Automatic (variable gear ratios)', 'Manual 4-spd'))

                      transmission
1                         Auto(L3)
2                         Auto(L4)
3                        Auto (S4)
4                  Automatic 6-spd
5                   Automatic (L3)
6 Automatic (variable gear ratios)
7                     Manual 4-spd

要求将自动(...)转换为自动... - 如自动(L3)到自动L3,自动(S4)到自动S4 - 并删除'(',')',' - '或''除了手动或自动后的第一个空格 - 如自动(6-spd)到自动6spd。

结果应该是:

                      transmission
1                     Automatic L3
2                     Automatic L4
3                     Automatic S4
4                   Automatic 6spd
5                     Automatic L3
6     Automatic variablegearratios
7                      Manual 4spd

目前我可能使用最愚蠢的方式:

transmission %>% 
  str_replace_all(' \\(',' ') %>%
  str_replace_all('Auto ','Automatic ') %>%
  str_replace_all(' ','') %>%
  str_replace_all('[()-]','') %>%
  str_replace_all('Automatic','Automatic ') %>%
  str_replace_all('Manual','Manual ')

但它是多余的不必要和耗时。 使用stringr包(str_xxx函数)和正则表达式执行此操作的正确和直接方法是什么?

提前致谢。

2 个答案:

答案 0 :(得分:2)

> mydf
                      transmission
1                         Auto(L3)
2                         Auto(L4)
3                        Auto (S4)
4                Automatic (6-spd)
5                   Automatic (L3)
6 Automatic (variable gear ratios)
7                     Manual 4-spd

> mydf$transmission_r = str_replace(mydf$transmission, "Auto(?:matic)?\\s?\\((.*)\\)", "Automatic \\1")
> mydf$transmission_r = str_replace_all(mydf$transmission_r, "-", "")
> mydf$transmission_r = str_replace_all(mydf$transmission_r, "(?<!Automatic|Manual)\\s", "")
> mydf
                      transmission                 transmission_r
1                         Auto(L3)                   Automatic L3
2                         Auto(L4)                   Automatic L4
3                        Auto (S4)                   Automatic S4
4                Automatic (6-spd)                 Automatic 6spd
5                   Automatic (L3)                   Automatic L3
6 Automatic (variable gear ratios)   Automatic variablegearratios
7                     Manual 4-spd                    Manual 4spd

解释

从“自动”一词开始,然后,使用不匹配的组(使用?:),表示可能存在“matic”(使用(matic)?)。接下来,指示可能存在空格(\\s?)。接下来,转义左括号(\\(),捕获匹配组((.*))内的所有文本,最后转义右括号(\\()。这是我们的正则表达式。然后我们将其替换为单词“Automatic”,然后替换在我们的第一个匹配组(\\1)中捕获的任何内容,这是括号内的任何内容。

删除连字符现在只是使用str_replace_all删除连字符,并删除“手动”或“自动”之间的所有空格,我们只是使用负面外观以确保空格不在前面用这些词语(使用(?<!Automatic|Manual))。

答案 1 :(得分:1)

正则表达式少了一点strsplit

mydf$transmission <- gsub("Auto(?=[^m])", "Automatic", mydf$transmission, perl=TRUE)
sapply(
  strsplit(gsub("[()-]", " ", mydf$transmission), "\\s+"),
  function(x) paste(x[1], paste0(x[-1],collapse="") )
)
#[1] "Automatic L3"                 "Automatic L4"                
#[3] "Automatic S4"                 "Automatic 6spd"              
#[5] "Automatic L3"                 "Automatic variablegearratios"
#[7] "Manual 4spd"