I have a matrix of values and zeros, where zero= NA
. The values are interspersed around the matrix, and what I want to do is interpolate the values of all the NA
values. This is the data:
I'm trying to guess all of these values by taking all the known values in my matrix, and multiplying the value by the distance (such that the further away a point is, the less influence it has). This is what the interpolated result looks like:
As you can see, this method is not very effective, it does affect the NA
s nearest to the known values, but then they quickly converge onto an average value. I think this is due to the fact that it's taking the ENTIRE RANGE, which has many ups and downs... rather than just the points nearest to it.
Obviously, matrix operations aren't my specialty... what do I need to change to correctly do the linear-interpolation?
Here's the code:
library(dplyr)
library(plotly)
Cont <- structure(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1816, 2320, 1406, 2028, 1760, 1932, 1630,
1835, 1873, 1474, 1671, 2073, 1347, 2131, 2038, 1969, 2036, 1602,
1986, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 2311, 1947, 2094, 1947, 2441, 1775, 1461, 1260,
1494, 2022, 1863, 1587, 2082, 1567, 1770, 2065, 1404, 1809, 1972,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 2314, 1595, 2065, 1870, 2178, 1410, 1994, 1979, 2111,
1531, 1917, 1559, 2109, 1921, 1606, 1469, 1601, 1771, 1771), .Dim = c(19L,
30L))
## First get real control values
idx <- which(Cont > 0, arr.ind=TRUE)
V <- Cont[idx]
ControlValues <- data.frame(idx,V)
## Make data.frame of values to fill
toFill <- which(Cont == 0, arr.ind=TRUE) %>% as.data.frame
toFill$V <- 0
## And now figure out the weighted value of each point
for (i in 1:nrow(toFill)){
toFill[i,] -> CurrentPoint
Xs <- (1/abs(CurrentPoint[,1] - ControlValues[,1]))
Xs[is.infinite(Xs)] <- 0
Xs <- Xs/sum(Xs)/100
Ys <- (1/abs(CurrentPoint[,2] - ControlValues[,2]))
Ys[is.infinite(Ys)] <- 0
Ys <- Ys/sum(Ys)/100
ControlValues1 <- data.frame(Xs,Ys)
toFill[i,3] <- sum(rowMeans(ControlValues1) * ControlValues$V)*100
}
## add back in the controls and reorder
bind_rows(ControlValues,toFill) -> Both
Both %>% arrange(row,col) -> Both
## and plot the new surface
NewCont <- matrix(Both$V,max(Both$row),max(Both$col),byrow = T)
plot_ly(z=NewCont, type="surface",showscale=FALSE)