I'm trying to figure out how to scale a set of numbers based on their relative proximity to a given number. Let's say I have [1, 3, 4, 4, 6, 7, 9, 10] for example, and n is 8. 7 and 9 would have a lot of weight, and 10's weight would be comparable, though lesser. 1's weight on the other hand would be relatively infinitesimal. How can I go about accomplishing this?
I came up with this (R):
test.2 <- function(vec, n) {
weight_vec <- 1 / abs(n-vec)
scaled <- vec * weight_vec
return(scaled)
}
which seems to work insofar as it scales the numbers based on their proximity, but the problem occurs, in this instance, in the difference for the results for 7 and 9 (and also 6 and 10):
test.2(c(1, 3, 4, 4, 6, 7, 9, 10), 8)
[1] 0.1428571 0.6000000 1.0000000 1.0000000 3.0000000 7.0000000 9.0000000 5.0000000
they should ideally output the same value. I should state that I do not have the mathematical know-how to claim to know what I am doing.
There are various ways to do this. One of which involves use of kernels. Note that the maximum weight should occur at 8 and equidistant points from 8 should have the same weights eg 7 and 9, 6 and 10 etc. Also note that the weights can be normalized by using prop.table
function. ie weights/sum(weights)
. The codes below provides unnormalized weights
## squared exponential kernel(gaussian/gibbs kernel)
vec <- 1:15
dnorm(x, 8) # you can play with sigma
## matern kernel
geoR::matern(abs(vec - 8), 1, 1) # You can play with phi, kappa
## power-exponential
exp(-abs(vec - 8)^1) # You can play with the power ie i used 1