Определите, какие элементы вектора частично соответствуют второму вектору, а какие нет (в R)

#r #grepl

Вопрос:

У меня есть вектор A , который содержит список родов, которые я хочу использовать для подмножества второго вектора, B . Я успешно использовал grepl для извлечения чего-либо, B что частично соответствует родам A . Ниже приведен воспроизводимый пример того, что я сделал.

Но теперь я хотел бы получить список , какие роды в чем- A то совпадают B , а какие-нет. Т. е. «сопоставленный» список будет содержать Cortinarius и Russula, а «несопоставимый» список будет содержать Лаккарию и Иноцибу. Есть какие-нибудь идеи о том, как это сделать? На самом деле мои векторы очень длинные, и названия родов B не все находятся в одном и том же положении среди другой информации.

 # create some dummy vectors
A <- c("Cortinarius","Laccaria","Inocybe","Russula")
B <- c("fafsdf_Cortinarius_sdfsdf","sdfsdf_Russula_sdfsdf_fdf","Tomentella_sdfsdf","sdfas_Sebacina","sdfsf_Clavulina_sdfdsf")

# extract the elements of B that have a partial match to anything in A.
new.B <- B[grepl(paste(A,collapse="|"), B)]

# But now how do I tell which elements of A were present in B, and which ones were not?
 

Ответ №1:

Мы могли бы использовать lapply или sapply для перебора шаблонов, а затем получить именованный вывод

 out <- setNames(lapply(A, function(x) grep(x, B, value = TRUE)), A)
 

Затем легче проверить те, которые возвращают пустые элементы

 > out[lengths(out) > 0]
$Cortinarius
[1] "fafsdf_Cortinarius_sdfsdf"

$Russula
[1] "sdfsdf_Russula_sdfsdf_fdf"

> out[lengths(out) == 0]
$Laccaria
character(0)

$Inocybe
character(0)
 

и получите names от этого

 > names(out[lengths(out) > 0])
[1] "Cortinarius" "Russula"    
> names(out[lengths(out) == 0])
[1] "Laccaria" "Inocybe" 
 

Ответ №2:

Вы можете использовать sapply с grepl для проверки A соответствия каждого значения с любым значением B .

 sapply(A, grepl, B)

#     Cortinarius Laccaria Inocybe Russula
#[1,]        TRUE    FALSE   FALSE   FALSE
#[2,]       FALSE    FALSE   FALSE    TRUE
#[3,]       FALSE    FALSE   FALSE   FALSE
#[4,]       FALSE    FALSE   FALSE   FALSE
#[5,]       FALSE    FALSE   FALSE   FALSE
 

Вы можете взять сумму этих значений по столбцам, чтобы получить количество совпадений.

 result <- colSums(sapply(A, grepl, B))
result

#Cortinarius    Laccaria     Inocybe     Russula 
#          1           0           0           1 

#values with at least one match
names(Filter(function(x) x > 0, result))
#[1] "Cortinarius" "Russula" 

#values with no match
names(Filter(function(x) x == 0, result))
#[1] "Laccaria" "Inocybe"