Как выполнить RMSE с отсутствующими значениями?
У меня есть огромный набор данных с 679 строками и 16 столбцами с 30% пропущенных значений. Поэтому я решил оспаривать эти недостающие значения функцией impute.knn из пакета impute, и я получил набор данных с 679 строками и 16 столбцами, но без отсутствующих значений.
Но теперь я хочу проверить точность с помощью RMSE, и я попробовал 2 варианта:
- загрузите пакет
hydroGOF
и примените функцию rmse
-
sqrt(mean (obs-sim)^2), na.rm=TRUE)
В двух ситуациях у меня есть ошибка: errors in sim .obs: non numeric argument to binary operator.
Это происходит потому, что исходный набор данных содержит значение NA
(некоторые значения отсутствуют).
Как я могу вычислить RMSE, если я удалю отсутствующие значения? Тогда obs
и sim
будут иметь разные размеры.
Ответы
Ответ 1
Как насчет просто...
sqrt( sum( (df$model - df$measure)^2 , na.rm = TRUE ) / nrow(df) )
Очевидно, что ваш файловый фрейм называется df
, и вам нужно принять решение о N (т.е. nrow(df)
содержит две строки с отсутствующими данными, вы хотите исключить их из N? Я бы предположил, да, поэтому вместо nrow(df)
вы, вероятно, захотите использовать sum( !is.na(df$measure) )
) или, следуя @Joshua просто
sqrt( mean( (df$model-df$measure)^2 , na.rm = TRUE ) )
Ответ 2
Функция rmse() в пакете R hydroGOF имеет параметр NA-remove:
# require(hydroGOF)
rmse(sim, obs, na.rm=TRUE, ...)
который, согласно документации, ожидает, когда na.rm
имеет значение TRUE:
"Когда значение NA находится на i-й позиции в obs OR sim, i-е значение
из obs AND sim удаляются перед вычислением. "
Без минимального воспроизводимого примера трудно сказать, почему это не сработало для вас.
Если вы хотите исключить недостающие значения перед вводом в функцию hydroGOF:: rmse(), вы можете сделать:
my.rmse <- rmse(df.sim[rownames(df.obs[!is.na(df.obs$col_with_missing_data),]),]
, df.obs[!is.na(df.obs$col_with_missing_data),])
предполагая, что у вас есть "имитированные" (вмененные) и "наблюдаемые" (оригинальные) наборы данных в разных кадрах данных с именем df.sim и df.obs, соответственно, которые были созданы из одного и того же исходного фрейма данных, поэтому имеют одинаковые размеры и имена строк.
Вот канонический способ сделать то же самое, если у вас более одного столбца с отсутствующими данными:
rows.wout.missing.values <- with(df.obs, rownames(df.obs[!is.na(col_with_missing_data1) & !is.na(col_with_missing_data2) & !is.na(col_with_missing_data3),]))
my.rmse <- rmse(df.sim[rows.wout.missing.values,], df.obs[rows.wout.missing.values,])
Ответ 3
Вычисление RMSE в R даже с отсутствующими значениями:
Математические обозначения:
![введите описание изображения здесь]()
Интуиция:
RMSE отвечает на вопрос: "Насколько похожи в среднем числа в списке d
и список p
"? Эти два списка должны иметь одинаковую длину. RMSE дает вам одно число, которое показывает, как далеко элементы d из элементов p.
Пример кода:
# Element 1 has zero error
# | Element 2 small error
# | | Element 3, large error
# | | | Has one missing value
# | | | | Two missing values
# v v v v v
#
d = c(0.000, 0.166, 0.333, NA, NA)
p = c(0.000, 0.254, 0.998, 0.31, NA)
rmse = function(predictions, targets){
#Option 1 to handle missing values (preferred)
#Wipe out both elements when either side has a
#missing value. This is dangerous because if
#you've got a lot of NA's, then the remaining
#elements will have more influence:
predictions[is.na(targets)] <- 0
targets[is.na(targets)] <- 0
targets[is.na(predictions)] <- 0
predictions[is.na(predictions)] <- 0
#alternatively you could just set the NA to some
#default value, but this is dangerous since it
#injects a constant bias into the equation proportional
#to how many NA are replaced.
#predictions[is.na(predictions)] <- 0
#targets[is.na(targets)] <- 0
return(sqrt(mean(((targets - predictions) ** 2))))
}
rmse_val = rmse(d, p)
print("rms error is: ")
print(rmse_val)
Отпечатки:
[1] "rms error is: "
[1] 0.387285
Для большей интуиции о том, как и почему это работает:
См. мой другой канонический ответ на RMSE, написанный на Python: fooobar.com/info/101114/...