Como encontrar os três valores mais próximos(mais próximos) dentro de um vetor?




(3)

Eu gostaria de descobrir os três números mais próximos em um vetor. Algo como

v = c(10,23,25,26,38,50)
c = findClosest(v,3)
c
23 25 26

Eu tentei com o tipo (colSums (as.matrix (dist (x)))) [1: 3], e tipo de obras, mas seleciona os três números com distância mínima global não os três números mais próximos.

Já existe uma resposta para o matlab, mas eu não sei como traduzi-lo para R:

%finds the index with the minimal difference in A
minDiffInd = find(abs(diff(A))==min(abs(diff(A))));
%extract this index, and it's neighbor index from A
val1 = A(minDiffInd);
val2 = A(minDiffInd+1);

Como encontrar dois valores mais próximos (mais próximos) dentro de um vetor no MATLAB?


Minha suposição é que para os n valores mais próximos, a única coisa que importa é a diferença entre v[i] - v[i - (n-1)] . Ou seja, encontrar o mínimo de diff(x, lag = n - 1L) .

findClosest <- function(x, n) {
  x <- sort(x)
  x[seq.int(which.min(diff(x, lag = n - 1L)), length.out = n)]
}

findClosest(v, 3L)

[1] 23 25 26

Uma idéia é usar a biblioteca do zoo para fazer uma operação de rolamento, ou seja,

library(zoo)
m1 <- rollapply(v, 3, by = 1, function(i)c(sum(diff(i)), c(i)))
m1[which.min(m1[, 1]),][-1]
#[1] 23 25 26

Ou faça isso em uma função,

findClosest <- function(vec, n) {
    require(zoo)
    vec1 <- sort(vec)
    m1 <- rollapply(vec1, n, by = 1, function(i) c(sum(diff(i)), c(i)))
    return(m1[which.min(m1[, 1]),][-1])
}

findClosest(v, 3)
#[1] 23 25 26

Vamos definir "números mais próximos" por "números com soma mínima de distâncias L1". Você pode conseguir o que você quer por uma combinação de soma diff e windowed.

Você poderia escrever uma função muito mais curta, mas eu escrevi passo a passo para facilitar o acompanhamento.

v <- c(10,23,25,26,38,50)

#' Find the n nearest numbers in a vector
#'
#' @param v Numeric vector
#' @param n Number of nearest numbers to extract
#'
#' @details "Nearest numbers" defined as the numbers which minimise the
#'   within-group sum of L1 distances.
#'   
findClosest <- function(v, n) {
  # Sort and remove NA
  v <- sort(v, na.last = NA)

  # Compute L1 distances between closest points. We know each point is next to
  # its closest neighbour since we sorted.
  delta <- diff(v)

  # Compute sum of L1 distances on a rolling window with n - 1 elements
  # Why n-1 ? Because we are looking at deltas and 2 deltas ~ 3 elements.
  withingroup_distances <- zoo::rollsum(delta, k = n - 1)

  # Now it's simply finding the group with minimum within-group sum
  # And working out the elements
  group_index <- which.min(withingroup_distances)
  element_indices <- group_index + 0:(n-1)

  v[element_indices]
}

findClosest(v, 2)
# 25 26
findClosest(v, 3)
# 23 25 26



r  

r