#r #string #pattern-matching
#r #строка #сопоставление с шаблоном
Вопрос:
У меня есть 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’ и, наконец, получить наилучший процент совпадения и повторить это для всех элементов ‘a’. В случае, если процентное соотношение получается одинаковым, мы всегда будем брать самый высокий процент. По сути, для каждого предложения у меня будет только одно совпадающее предложение в виде одного процента совпадения. В случае, если у нас одинаковый самый высокий процент, мы возьмем 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)
Ответ №1:
Вы также можете использовать 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
функцию для такого извлечения строки
Комментарии:
1. Вы предположили, что
Matching_String
это уже существует, что, вероятно, не так. Я признаю, что это несколько сбивает с толку.2. Когда я пытаюсь использовать ‘map2_dbl’, он показывает мне ошибку Error: .x (579) и .y (4) имеют разную длину
Ответ №2:
Полезен вывод 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")
Комментарии:
1. Поскольку мой набор данных довольно длинный, ‘внешняя’ функция выполняется вечно. Также, что такое ‘m’ в Matching_String=b[m] ? Когда я пытаюсь использовать ‘map2_dbl’, он показывает мне ошибку Error:
.x
(579) и.y
(4) имеют разную длину2. О, я забыл вставить строку кода для
m
, теперь исправлено. Я дал вам решение для предоставленных вами данных. Если это не работает для ваших исходных данных, вам следует привести пример получше, поскольку я с трудом могу их угадать. И в моем коде этого нетmap2_dbl
?