Рассчитать средневзвешенное значение с различными весами и пропущенными значениями в R - PullRequest
0 голосов
/ 12 марта 2019

Я пытаюсь вычислить средневзвешенное значение для 3 столбцов, в которых веса определяются на основе количества пропущенных значений в строке.

Воспроизводимый пример:

# Some simulated data

N <- 50
df <- data.table(int_1 = runif(N,1000,5000), int_2 = runif(N,1000,5000), int_3 = runif(N,1000,5000))
df[-1] <- lapply(df[-1], function(x) { x[sample(c(1:N), floor(N/10))] <- NA ; x })

# Function to calculate weighted average
# The weights are flexible and are input by user

a = 5
b = 3
c = 2
i = 10

wa_func <- function(x,y,z){

  if(!(is.na(x) & is.na(y) & is.na(z))){

    wt_avg <- (a/i)* x + (b/i) * y + (c/i) * z

  } else if(!is.na(x) & !is.na(y) & is.na(z)){

    wt_avg <- (a/(i-c))* x + (b/(i-c)) * y

  } else if(!is.na(x) & is.na(y) & is.na(z)){

    wt_avg <- a/(i-(b+c))* x

  }

  return(wt_avg)
}

df[, weighted_avg_int := mapply(wa_func,int_1,int_2,int_3)]

Но функция выдает NA для любого пропущенного значения в строке. Что мне здесь не хватает?

Заранее спасибо.

1 Ответ

1 голос
/ 12 марта 2019

Вам необходимо изменить условие первого if в вашей функции:

wa_func <- function(x, y, z) {
  if (!(is.na(x) | is.na(y) | is.na(z))) {
    wt_avg <- (a / i) * x + (b / i) * y + (c / i) * z

  } else if (!is.na(x) & !is.na(y) & is.na(z)) {
    wt_avg <- (a / (i - c)) * x + (b / (i - c)) * y

  } else if (!is.na(x) & is.na(y) & is.na(z)) {
    wt_avg <- a / (i - (b + c)) * x

  }

  return(wt_avg)
}

Вы можете улучшить функцию, чтобы вам не нужно было mapply, добавив в нее функцию Vectorise():

wa_func <- Vectorize(function(x, y, z) {
  a <- 5 # part of the function?
  b <- 3
  c <- 2
  i <- 10

  if (!(is.na(x) | is.na(y) | is.na(z))) {
    (a / i) * x + (b / i) * y + (c / i) * z
  } else if (!is.na(x) & !is.na(y) & is.na(z)) {
    (a / (i - c)) * x + (b / (i - c)) * y
  } else if (!is.na(x) & is.na(y) & is.na(z)) {
    a / (i - (b + c)) * x
  }
  # no need for return()
})
...