# CSC 121, Jan-Apr 2017, Small Assignment #3, Function definition na_interpolate <- function (v) { # Create a vector, prev_not_na, that for each position, i, in v, # contains the index of the nearest element of v at or before i # that is not NA, or zero if there is none. This is done by # starting with a vector of zeros, and then updating it while # scanning v forwards. prev_not_na <- numeric(length(v)) # initially all zeros for (i in 1:length(v)) { if (!is.na(v[i])) { # If this is not an NA, the index is just for this element. prev_not_na[i] <- i } else if (i > 1) { # If this is an NA, the index of the previous non-NA element is # the same as for the previous position (unless we're at the start). prev_not_na[i] <- prev_not_na[i-1] } } # Create a vector, next_not_na, that for each position, i, in v, # contains the index of the nearest element of v at or after i # that is not NA, or zero if there is none. This is done by # starting with a vector of zeros, and then updating it while # scanning v backwards. next_not_na <- numeric(length(v)) # initially all zeros for (i in length(v):1) { if (!is.na(v[i])) { # If this is not an NA, the index is just for this element. next_not_na[i] <- i } else if (i < length(v)) { # If this is an NA, the index of the next non-NA element is # the same as for the next position (unless we're at the end). next_not_na[i] <- next_not_na[i+1] } } # We can now fill in the NA values in v making use of the indexes of # adjacent non-NA elements in prev_not_na and next_not_na. for (i in 1:length(v)) { if (is.na(v[i])) { if (prev_not_na[i] != 0 && next_not_na[i] != 0) { # Interpolate between the nearest non-NA values on each side. d1 <- i - prev_not_na[i] # distance to previous non-NA element x1 <- v[prev_not_na[i]] # value of previous non-NA element d2 <- next_not_na[i] - i # distance to next non-NA element x2 <- v[next_not_na[i]] # value of next non-NA element v[i] <- (d1*x2 + d2*x1) / (d1 + d2) } else if (prev_not_na[i] != 0) { # Non-NA value before, but not after. v[i] <- v[prev_not_na[i]] } else if (next_not_na[i] != 0) { # Non-NA value after, but not before. v[i] <- v[next_not_na[i]] } } } v }