正则表达式双列匹配R

时间:2016-01-23 20:56:26

标签: regex r if-statement stringr

这是我昨天问的一个问题: Partial string match two columns R

提供的答案很棒;然而,我发现许多物种也没有被直接引用,即乌龟从来没有在dats $ product.authorise中直接描述,但是“异国情调”#39;是一个可以接受的比赛。

dats<-data.frame(ID=c(1:4),species=c("dog","cat","rabbit","tortoise"),
            species.descriptor=c("all animal dog","all animal cat","rabbit exotic","tortoise exotic"),
            product=c(1,2,3,4),product.authorise=c("all animal dog cat rabbit","cat horse pig",
            "dog cat","exotic"))
dats
  ID  species species.descriptor product         product.authorise
   1      dog     all animal dog       1 all animal dog cat rabbit
   2      cat     all animal cat       2             cat horse pig
   3   rabbit      rabbit exotic       3                   dog cat
   4 tortoise    tortoise exotic       4                    exotic

我提出了一个解决方案,它基于将$ species.descriptor和$ product.authorise绑定在一起,然后将该行指定为&#39; TRUE&#39;如果特定的reg exp在字段中出现两次或多次,如下所示:

library(stringr)
dats$bound<-paste(dats$product.authorise, dats$species.descriptor)

species_descriptor<-c("all animal","dog","cat","rabbit","exotic","horse","pig","tortoise")
species_descriptor<-setNames(nm=species_descriptor)
result<-ifelse(sapply(species_descriptor, str_count, string=dats$bound)>=2,"TRUE","FALSE")
result<-as.data.frame(result)

result$AuthorisedCount<-apply(result[,1:ncol(result)],MARGIN=1,function(x){sum(x=="TRUE",na.rm=T)})
result$SpeciesAuthorised<-ifelse(result$AuthorisedCount>=1,"TRUE","FALSE")

dats<-cbind(dats, result$SpeciesAuthorised)
names(dats)[7]<-"SpeciesAuthorised" 
dats$bound<-NULL

dats
  ID  species species.descriptor product         product.authorise SpeciesAuthorised
   1      dog     all animal dog       1 all animal dog cat rabbit              TRUE
   2      cat     all animal cat       2             cat horse pig              TRUE
   3   rabbit      rabbit exotic       3                   dog cat             FALSE
   4 tortoise    tortoise exotic       4                    exotic              TRUE

这很好,在更大的数据集上工作很快;但是,我知道可能有一种更优雅的做事方式。我想知道是否有人有任何建议?

3 个答案:

答案 0 :(得分:2)

使用sapply函数调用和bound变量生成相同的结果:

bound<-paste(dats$product.authorise, dats$species.descriptor)
dats$SpeciesAuthorised <- as.logical(rowSums(sapply(species_descriptor, str_count, string=bound)>=2))
# ID  species species.descriptor product         product.authorise SpeciesAuthorised
# 1  1      dog     all animal dog       1 all animal dog cat rabbit              TRUE
# 2  2      cat     all animal cat       2             cat horse pig              TRUE
# 3  3   rabbit      rabbit exotic       3                   dog cat             FALSE
# 4  4 tortoise    tortoise exotic       4                    exotic              TRUE

答案 1 :(得分:1)

扩展你提到的帖子会有用吗?

neuePerson

我刚刚在函数中添加了一个OR运算符,以检测species.descriptor中product.authorise中的模式。

dats$SpeciesAuthorised <-  with(dats, 
                                str_detect(species.descriptor, species) & 
                                  (str_detect(product.authorise, species) | str_detect(species.descriptor,product.authorise))
)

答案 2 :(得分:1)

您可以使用函数any

来减少代码
bound  <- paste(dats$product.authorise, dats$species.descriptor)
result <- ifelse(sapply(species_descriptor, str_count, string=bound)>=2, TRUE, FALSE)

dats$SpeciesAuthorised <- apply(result, 1, any)

无需将结果设置为"TRUE""FALSE"作为字符,使用逻辑。

此外,如果您想使代码更加干净和可读,您可以定义自己的功能:

isSpeciesAuthorised = function(data, species_descriptor) {
  bound  <- paste(data$product.authorise, data$species.descriptor)
  result <- ifelse(sapply(species_descriptor, str_count, string=bound)>=2, TRUE, FALSE)

  return(apply(result, 1, any)) 
}

然后使用它们:

dats$SpeciesAuthorised <- isSpeciesAuthorised(data=dats, species_descriptor)