Проблема легко решается, если вместо создания матрицы для хранения коэффициентов они сохраняются в list
.Таким образом, не будет никаких предметов для замены, обо всем позаботятся позже.
В следующем коде я использую встроенный набор данных iris
, меняя имя ответа на area
.
wdbc <- iris
names(wdbc)[1] <- "area"
fitted_value <- rep(0, nrow(wdbc))
estcoef <- vector("list", length = nrow(wdbc))
# LOOCV split leave one out cross validation
for(i in 1:nrow(wdbc)){
validation <- wdbc[i,]
training <- wdbc[-i, ]
model1 <- lm(area ~ ., data = training)
fitted_value[i] <- predict(model1, newdata = validation)
estcoef[[i]] <- coef(model1)
}
estcoef <- do.call(rbind, estcoef)
meancoef <- colMeans(estcoef) # coefficent means
Edit.
Оператор жалуется на ошибку:
Ошибка в model.frame.default (Условия, новые данные, na.action = na.action, xlev = object $ xlevels):
фактор месяц имеет новый уровень nov
Это связано с тем, что в наборе данных имеется только одна строка с month == "nov"
, поэтому при подборе модели с этой одной опущенной строкой набор данных validation
имеетзначение в столбце month
, которого нет в наборе данных training
и predict
не знает, что с ним делать.
Решение состоит в том, чтобы использовать tryCatch
, чтобы перехватить ошибку и позволить коду продолжить работу.Функция ниже - это повторение кода выше с вызовом tryCatch
.Возвращает средние коэффициенты и подогнанные значения.Когда predict
выдает ошибку, возвращается значение NaN
.Измените это по желанию.
fitModelLOOCV <- function(DF){
fitted_value <- rep(0, nrow(DF))
estcoef <- vector("list", length = nrow(DF))
# LOOCV split leave one out cross validation
for(i in 1:nrow(DF)){
validation <- DF[i,]
training <- DF[-i, ]
model1 <- lm(area ~ ., data = training)
fitted_value[i] <- tryCatch(predict(model1, newdata = validation),
error = function(e) {print(e); NaN})
estcoef[[i]] <- coef(model1)
}
estcoef <- do.call(rbind, estcoef)
meancoef <- colMeans(estcoef) # coefficent means
list(meancoef = meancoef, fitted = fitted_value)
}
fitModelLOOCV(wdbc)
Альтернативой является удаление значения проблемы перед запуском функции.(Может быть, только одна точка данных не так важна.)
wdbc2 <- wdbc[-which(wdbc$month == "nov"), ]
fitModelLOOCV(wdbc2)