Соответствующая строка без использования цикла - PullRequest
0 голосов
/ 14 марта 2019

У меня есть 2 набора данных.

a <- c("adidas shoes","hot tea","pizza","hill station")
b <- c("shoes","plastic cup","pizza","I love to go to hill","travelling in motor van",
       "buy adidas shoes","run using adidas shoes")

Я хочу сопоставить каждое слово в каждом предложении 1-го вектора со всеми элементами второго вектора и выбрать то, в котором совпадает максимальное количество слов.

Для этого я использовал следующий код:

a_split <- unlist(strsplit(a[1,], " "))
b_split <- unlist(strsplit(b[1,], " "))
a$match_perc[1] <- length(intersect(a_split, b_split))/length(a_split)*100

так что, по сути, я пытаюсь сделать так: сопоставьте «adidas» и «shoes» [1-й элемент вектора «a»] со всеми элементами вектора «b» и, наконец, придумали лучшее соответствующий процент и повторите это для всех элементов «а». Если процент будет одинаковым, мы всегда будем брать самый высокий процент. По сути, для каждого предложения у меня будет только одно соответствующее предложение в виде одного соответствующего процента. Если у нас одинаковый наибольший процент, мы примем 1-й матч.

Ожидаемый результат ниже:

a <- c("adidas shoes","hot tea","pizza","hill station")
Matching_String <- c("buy adidas shoes","NA","pizza","I love to go to hill")
match_perc <- c(100,0,100,50)
final_op <- data.frame(a,Matching_String,match_perc)

Ответы [ 2 ]

0 голосов
/ 14 марта 2019

Полезен вывод strsplit в виде списков.

as <- strsplit(a, " ")
bs <- strsplit(b, " ")

Вы можете создать соответствующую матрицу этих списков, векторизовав вашу функцию и используя outer.

matchFun <- function(x, y) length(intersect(x, y)) / length(x) * 100
mx <- outer(as, bs, Vectorize(matchFun))

Затем поместите максимумы в векторы.

m <- apply(mx, 1, which.max)  # the maximum column of each row

z <- unlist(apply(p, 1, function(x) x[which.max(x)]))  # maximum percentage
z[z == 0] <- NA  # this gives you the NA if you want it

Наконец, поместите результат в кадр данных.

data.frame(a, Matching_String=b[m], match_perc=z)

#              a      Matching_String match_perc
# 1 adidas shoes     buy adidas shoes        100
# 2      hot tea                shoes         NA
# 3        pizza                pizza        100
# 4 hill station I love to go to hill         50

Данные

a <- c("adidas shoes","hot tea","pizza","hill station")
b <- c("shoes","plastic cup","pizza","I love to go to hill","travelling in motor van",
       "buy adidas shoes","run using adidas shoes")
0 голосов
/ 14 марта 2019

Вы также можете использовать purrr::map функции:

library(purrr)
match_perc <- map2_dbl(a, Matching_String, function(a, b) {
  a_split <- unlist(strsplit(a, " "))
  b_split <- unlist(strsplit(b, " "))
  length(intersect(a_split, b_split))/length(a_split)*100
})
final_op <- data.frame(a,Matching_String,match_perc)
final_op
             a      Matching_String match_perc
1 adidas shoes     buy adidas shoes        100
2      hot tea                   NA          0
3        pizza                pizza        100
4 hill station I love to go to hill         50

Также посмотрите на stringr::str_extract_all функцию для такого извлечения строки

...