8

我有以下数据:

temp<-c("AIR BAGS:FRONTAL" ,"SERVICE BRAKES HYDRAULIC:ANTILOCK",
    "PARKING BRAKE:CONVENTIONAL",
    "SEATS:FRONT ASSEMBLY:POWER ADJUST",
    "POWER TRAIN:AUTOMATIC TRANSMISSION",
    "SUSPENSION",
    "ENGINE AND ENGINE COOLING:ENGINE",
    "SERVICE BRAKES HYDRAULIC:ANTILOCK",
    "SUSPENSION:FRONT",
    "ENGINE AND ENGINE COOLING:ENGINE",
    "VISIBILITY:WINDSHIELD WIPER/WASHER:LINKAGES")

我想创建一个新向量,在存在“:”的情况下仅保留第一个“:”之前的文本,而当“:”不存在时,则保留整个单词。

我曾尝试使用:

temp=data.frame(matrix(unlist(str_split(temp,pattern=":",n=2)), 
+                        ncol=2, byrow=TRUE))

但在没有“:”的情况下不起作用

我知道这个问题非常类似于: truncate string from a certain character in R,它使用:

sub("^[^.]*", "", x)

但是我对正则表达式不是很熟悉,并且一直在努力反转该示例以仅保留字符串的开头。

4

5 回答 5

15

你可以用一个简单的正则表达式来解决这个问题:

sub("(.*?):.*", "\\1", x)
 [1] "AIR BAGS"                  "SERVICE BRAKES HYDRAULIC"  "PARKING BRAKE"             "SEATS"                    
 [5] "POWER TRAIN"               "SUSPENSION"                "ENGINE AND ENGINE COOLING" "SERVICE BRAKES HYDRAULIC" 
 [9] "SUSPENSION"                "ENGINE AND ENGINE COOLING" "VISIBILITY"     

正则表达式的工作原理:

  • "(.*?):.*"寻找一组重复的任何字符,但不要贪婪地.*修改它。?这应该后跟一个冒号,然后是任何字符(重复)
  • 用括号内的位替换整个字符串 -"\\1"

需要理解的是,任何正则表达式匹配默认都是贪婪的。通过将其修改为非贪婪,第一个模式匹配不能包含冒号,因为括号后面的第一个字符是冒号。冒号后面的正则表达式恢复到默认值,即贪心。

于 2012-06-04T15:21:39.087 回答
9

另一种方法是查找第一个“:”并将其替换为什么都没有:

yy <- sub(":.*$", "", yy )

如果没有找到“:”,那么什么都不会被替换,你会得到整个原始字符串。如果有一个“:”,那么第一个与它之后的所有内容一起匹配,然后将其替换为空(“”),这将删除它并将所有内容保留到第一个冒号。

于 2012-06-04T15:44:30.387 回答
3

这行得通吗(假设您的数据在字符向量中):

x <- c('foobar','foo:bar','foo1:bar1 foo:bar','foo bar')
> sapply(str_split(x,":"),'[',1)
[1] "foobar"  "foo"     "foo1"    "foo bar"
于 2012-06-04T15:14:26.953 回答
3

很抱歉将此添加为答案。响应时间:

> yy<-rep("foo1:bar1",times=100000)
> system.time(yy1<-sapply(strsplit(yy,":"),'[',1))
   user  system elapsed 
   0.26    0.00    0.27 
> 
> system.time(yy2<-sub("(.*?):.*", "\\1", yy))
   user  system elapsed 
    0.1     0.0     0.1 
> 
> system.time(yy3 <- sub(":.*$", "", yy ))
   user  system elapsed 
   0.08    0.00    0.07 
> 
> system.time(yy4<-gsub("([^:]*).*","\\1",yy))
   user  system elapsed 
   0.09    0.00    0.09 

正则表达式大致相当于 strsplit 需要更长的时间

于 2012-06-04T15:52:50.810 回答
1

在这种情况下

yy<-c("AIR BAGS:FRONTAL",
"SERVICE BRAKES HYDRAULIC:ANTILOCK",
"PARKING BRAKE:CONVENTIONAL",
"SEATS:FRONT ASSEMBLY:POWER ADJUST",
"POWER TRAIN:AUTOMATIC TRANSMISSION",
"SUSPENSION",
"ENGINE AND ENGINE COOLING:ENGINE",
"SERVICE BRAKES HYDRAULIC:ANTILOCK",
"SUSPENSION:FRONT",
"ENGINE AND ENGINE COOLING:ENGINE",
"VISIBILITY:WINDSHIELD WIPER/WASHER:LINKAGES")
yy<-gsub("([^:]*).*","\\1",yy)
yy

可能适合你

于 2012-06-04T15:18:59.097 回答