Determine the location(s) in character vector that match maximum number of matches from a match vector [R]

Viewed 60

How can I test which element of a character vector (testvec) has the most words from another character vector (matchvec)?

testvec <- c("making words up here for a test significant words",
             "this one is really important and significant/crucial",
             "can you see which has most significant/important words?",
             "this one isn't desired at all")

matchvec <- c("important", "significant", "crucial")

desired_result (since the second from testvec has the most words from matchvec)
[1] 2

If I change it so that two have the same max I want to return both indexes:

matchvec2 <- c("important", "significant")

desired_result2 (since the second/third from testvec have the most words from matchvec2)
    [1] 2
    [2] 3
3 Answers

One possibility using stringr could be:

count <- str_count(testvec, paste(matchvec, collapse = "|"))
which(count == max(count))

[1] 2

The same with just base R:

count <- rowSums(sapply(matchvec, function(x) grepl(x, testvec)))
which(count == max(count))

Or if there are repeated words (as proposed by @Henrik):

count <- lengths(gregexpr(paste(matchvec, collapse = "|"), testvec))
which(count == max(count))

A possibility:

 res<-lapply(testvec, function(x) stringr::str_count(matchvec)) 
which.max(Map(sum,res))
[1] 2

Or use a purely tidyverse solution and extract the indices that are true:

plyr::ldply(testvec,
            function(x)
              all(stringr::str_count(x,matchvec)>0))
 which(res==TRUE)
[1] 2

This should also work:

testvec <- c("making words up here for a test significant words", "this one is really important and significant/crucial", "can you see which has most significant/important words?", "this one isn't desired at all")

matchvec <- c("important", "significant", "crucial")

matches <- sapply(testvec, 
       function(x){sum(sapply(matchvec,
                              function(y){
                                grepl(y,x)
                              }))})

matches[matches == max(matches)]
#> this one is really important and significant/crucial 
#>                                                    3

And if you do only want to have the positions returned use which:

which(matches == max(matches)])
Related