Сопоставление элементов двух векторов на основе близости - PullRequest
0 голосов
/ 02 декабря 2018

Я получил два вектора:

a<-c(268, 1295, 1788, 2019, 2422)
b<-c(266,  952, 1295, 1791, 2018)

Я хочу сопоставить элементы b с элементами a, основываясь на наименьшей разнице.Таким образом, a [1] будет соответствовать b [1].Однако каждый элемент может быть сопоставлен только с одним другим элементом.Возможно, что элементы не могут быть сопоставлены.Если два элемента b имеют наименьшую разницу с одним и тем же элементом в a, то элемент с меньшей разностью сопоставляется.

Например, 952 и 1295 ближе всего к элементу a [2], так как 1295 ближе(в этом случае даже равный) a [2] он будет сопоставлен с 1295. Окончательное решение для этого конкретного примера должно выглядеть следующим образом.

268  NA  1295 1788 2019 2422
266 952  1295 1791 2018 NA

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

С моими возможностями кодирования я бы использовал тонны операторов if для решения этой проблемы.Но мне было интересно, является ли это известной проблемой, и мне известна терминология такого рода или есть у кого-нибудь идея для элегантного решения

1 Ответ

0 голосов
/ 02 декабря 2018

Базовый подход R, хотя, вероятно, не самый элегантный:

aux1 <- apply(abs(outer(a, b, `-`)), 2, function(r) c(min(r), which.min(r)))
colnames(aux1) <- 1:length(b)
aux2 <- tapply(aux1[1, ], factor(aux1[2, ], levels = 1:length(a)),
               function(x) as.numeric(names(which.min(x))))
rbind(cbind(a, b = b[aux2]), cbind(a = NA, b = b[-aux2[!is.na(aux2)]]))
#         a    b
# [1,]  268  266
# [2,] 1295 1295
# [3,] 1788 1791
# [4,] 2019 2018
# [5,] 2422   NA
# [6,]   NA  952

Здесь aux1 содержит самые близкие a элементы к b (2-я строка) и соответствующие расстояния(1-й ряд).

tmp
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    2  343    0    3    1
# [2,]    1    2    2    3    4

Тогда aux2 может быть уже достаточно для ваших целей.

out
#  1  2  3  4  5 
#  1  3  4  5 NA 

aux1 показал некоторые связи, но aux2 теперь дает какой элементa (2-я строка) следует назначить элементу b (имена).Затем в последней строке мы связываем остальные элементы.


В более сложном случае имеем

a <- c(932, 1196, 1503, 2819, 3317, 3845, 4118, 4544)
b <- c(1190, 1498, 2037, 2826, 3323, 4128, 4618, 1190, 1498, 2037, 2826, 3323, 4128, 4618)

# ....

rbind(cbind(a, b = b[aux2]), cbind(a = NA, b = b[-aux2[!is.na(aux2)]]))    
#          a    b
#  [1,]  932   NA
#  [2,] 1196 1190
#  [3,] 1503 1498
#  [4,] 2819 2826
#  [5,] 3317 3323
#  [6,] 3845   NA
#  [7,] 4118 4128
#  [8,] 4544 4618
#  [9,]   NA 2037
# [10,]   NA 1190
# [11,]   NA 1498
# [12,]   NA 2037
# [13,]   NA 2826
# [14,]   NA 3323
# [15,]   NA 4128
# [16,]   NA 4618
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...