Почему na.rm = TRUE не работает для взвешенного SD в R? - PullRequest
4 голосов
/ 30 января 2020

У меня есть датафрейм из 10 столбцов с ценами на жилье, который в некоторых случаях включает NA. Я хочу создать новый столбец weighted sd, но для строк, имеющих несколько NA, я получаю следующую ошибку:

Error in e2[[j]] : subscript out of bounds

Что я использую для каждой строки (и работает для строк без NA):

weighted.sd(my.df[40,2:10], c(9,9,9,9,9,9,9,9,9), na.rm = TRUE)

Пример

library(radiant.data)
data("mtcars")
mtcars[mtcars == 0] <- NA
weighted.sd(mtcars[18,1:11], c(11,11,11,11,11,11,11,11,11,11,11), na.rm = TRUE)#works
weighted.sd(mtcars[5,1:11], c(11,11,11,11,11,11,11,11,11,11,11), na.rm = TRUE)#issue here

В чем здесь проблема и как я могу создать новый столбец с взвешенным SD для каждой строки?

Ответы [ 2 ]

1 голос
/ 30 января 2020

Похоже, проблема в том, что weighted.sd() не будет работать так, как вы ожидаете в строках фрейма данных.

При запуске weighted.sd мы можем увидеть код:

weighted.sd <- function (x, wt, na.rm = TRUE) 
{
  if (na.rm) {
    x <- na.omit(x)
    wt <- na.omit(wt)
  }
  wt <- wt/sum(wt)
  wm <- weighted.mean(x, wt)
  sqrt(sum(wt * (x - wm)^2))
}

В вашем примере вы вводите не вектор для x, а одну строку фрейма данных. Функция na.omit(x) удалит всю строку из-за значений NA, а не из элементов вектора.

Вы можете попытаться преобразовать строку в вектор с помощью as.numeric(), но это не удастся для эта функция также из-за того, как NA удалена из wt.

Кажется, что-то вроде этого, вероятно, то, что вы хотите. Конечно, вы должны быть осторожны, чтобы подавать в допустимые столбцы для x.

weighted.sd2 <- function (x, wt, na.rm = TRUE) {

  x <- as.numeric(x)

  if (na.rm) {
    is_na <- is.na(x)

    x <- x[!is_na]
    wt <- wt[!is_na]
  }

  wt <- wt/sum(wt)
  wm <- weighted.mean(x, wt)
  sqrt(sum(wt * (x - wm)^2))
}
weighted.sd2(mtcars[18,1:11], c(11,11,11,11,11,11,11,11,11,11,11), na.rm = TRUE)#works
# [1] 26.76086
weighted.sd2(mtcars[5,1:11], c(11,11,11,11,11,11,11,11,11,11,11), na.rm = TRUE)#issue here
# [1] 116.545

Чтобы применить это ко всем столбцам, вы можете использовать apply().

mtcars$weighted.sd <- apply(mtcars[,1:11], 1, weighted.sd2, wt = rep(11, 11))
                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb weighted.sd
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46 NA  1    4    4    52.61200
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02 NA  1    4    4    52.58011
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1    37.06108
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1 NA    3    1    78.36300
Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02 NA NA    3    2   116.54503
...
0 голосов
/ 30 января 2020

Если вы нажмете CTRL + щелчок по функции weigted.sd, вы увидите исходный код:

function (x, wt, na.rm = TRUE) 
{
  if (na.rm) {
    x <- na.omit(x)
    wt <- na.omit(wt)
  }
  wt <- wt/sum(wt)
  wm <- weighted.mean(x, wt)
  sqrt(sum(wt * (x - wm)^2))
}

Когда вы его запустите, вектор значений содержит значения без NA, и он уменьшается. Но весовой вектор имеет ту же длину, что и раньше, что приводит к ошибке.

Решение будет таким:

weighted.sd(mtcars[5,!is.na(mtcars[5,1:11])], 
c(11,11,11,11,11,11,11,11,11,11,11)[!is.na(mtcars[5,1:11])], na.rm = TRUE)

Это не элегантно ... Но оно делает свою работу!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...