我可以指示预测忽略 R 中的错误行吗?
Can I instruct predict to ignore error rows in R?
我有一个训练数据集,我正在从中(随机)采样以在 R 中训练模型。
sampleSize <- floor(0.1 * nrow(trainingDataFrame))
train_index <- sample(seq_len(nrow(trainingDataFrame)), size = sampleSize)
trainDF <- trainingDataFrame[train_index,]
fit <- train(dependentVariable ~ ., data=trainDF,
trControl = trainControl(method = "cv",number = 10),method="lm")
然后我使用该模型在一个单独的测试数据集中 predict
值。但是,有一个因子字段,对于我的测试数据集中的某些行,偶尔会有训练集中没有遇到的值,因为我正在为训练集随机抽样。这会导致 "factor ... has new levels"
错误。
我实际上是在多次迭代中重复这个 sample-train-predict 过程,所以每个测试数据集记录最终很可能会有一些有效的预测。因此,对于我的用例,某些记录在任何特定迭代中都无法 predict
实际上是可以的。我不想从模型训练中排除相关领域。
相反,是否可以指示 predict
函数为这些无效行提供 na
或其他一些默认值?
这是一种可能性。
关键是定义您自己的 predict
函数,该函数比较来自 lm
对象的 factor
变量与来自 newdata
的变量的水平。然后,我们 predict
仅针对那些具有匹配 factor
水平的观察结果,并且 return NA
用于所有其他观察结果。
我将使用 mtcars
数据进行演示。
让我们首先创建包含一个数字响应 (mpg
) 和 3 个分类预测变量 (cyl
、gear
、carb
的示例数据).
library(tidyverse)
df <- mtcars %>%
select(mpg, cyl, gear, carb) %>%
mutate_at(vars(-mpg), as.factor)
然后我们在观察训练数据集上训练模型,这些训练数据集只有 cyl
和 gear
的一些(但不是全部)因子水平。
df.train <- df %>% filter(cyl %in% c(4, 6) & gear %in% c(3, 4))
我们拟合一个简单的线性模型。
fit <- lm(mpg ~ ., data = df.train)
我们现在定义一个自定义函数,将 newdata
拆分为具有 (1) 匹配 factor
水平的观察结果,我们可以 predict
对其做出响应,以及 ( 2) "novel" 水平,我们 return NA
作为回应。
factor
所有分类变量的水平存储在 fit$xlevels
中作为 list
。我们使用 purrr::imap
和 purrr::reduce(..., intersect)
来确定 newdata
中具有匹配 factor
水平的那些观察的行索引。
my.predict <- function(fit, newdata) {
lvls <- fit$xlevels
idx <- reduce(imap(lvls, ~which(newdata[, .y] %in% .x)), intersect)
res <- rep(NA, nrow(newdata))
res[idx] <- predict(fit, newdata = newdata[idx, ])
return(res)
}
我们在完整的 df
数据集上确认结果:
df$pred <- my.predict(fit, df)
df
# mpg cyl gear carb pred
#1 21.0 6 4 4 19.75
#2 21.0 6 4 4 19.75
#3 22.8 4 4 1 29.10
#4 21.4 6 3 1 19.75
#5 18.7 8 3 2 NA
#6 18.1 6 3 1 19.75
#7 14.3 8 3 4 NA
#8 24.4 4 4 2 24.75
#9 22.8 4 4 2 24.75
#10 19.2 6 4 4 19.75
#11 17.8 6 4 4 19.75
#12 16.4 8 3 3 NA
#13 17.3 8 3 3 NA
#14 15.2 8 3 3 NA
#15 10.4 8 3 4 NA
#16 10.4 8 3 4 NA
#17 14.7 8 3 4 NA
#18 32.4 4 4 1 29.10
#19 30.4 4 4 2 24.75
#20 33.9 4 4 1 29.10
#21 21.5 4 3 1 21.50
#22 15.5 8 3 2 NA
#23 15.2 8 3 2 NA
#24 13.3 8 3 4 NA
#25 19.2 8 3 2 NA
#26 27.3 4 4 1 29.10
#27 26.0 4 5 2 NA
#28 30.4 4 5 2 NA
#29 15.8 8 5 4 NA
#30 19.7 6 5 6 NA
#31 15.0 8 5 8 NA
#32 21.4 4 4 2 24.75
我有一个训练数据集,我正在从中(随机)采样以在 R 中训练模型。
sampleSize <- floor(0.1 * nrow(trainingDataFrame))
train_index <- sample(seq_len(nrow(trainingDataFrame)), size = sampleSize)
trainDF <- trainingDataFrame[train_index,]
fit <- train(dependentVariable ~ ., data=trainDF,
trControl = trainControl(method = "cv",number = 10),method="lm")
然后我使用该模型在一个单独的测试数据集中 predict
值。但是,有一个因子字段,对于我的测试数据集中的某些行,偶尔会有训练集中没有遇到的值,因为我正在为训练集随机抽样。这会导致 "factor ... has new levels"
错误。
我实际上是在多次迭代中重复这个 sample-train-predict 过程,所以每个测试数据集记录最终很可能会有一些有效的预测。因此,对于我的用例,某些记录在任何特定迭代中都无法 predict
实际上是可以的。我不想从模型训练中排除相关领域。
相反,是否可以指示 predict
函数为这些无效行提供 na
或其他一些默认值?
这是一种可能性。
关键是定义您自己的 predict
函数,该函数比较来自 lm
对象的 factor
变量与来自 newdata
的变量的水平。然后,我们 predict
仅针对那些具有匹配 factor
水平的观察结果,并且 return NA
用于所有其他观察结果。
我将使用 mtcars
数据进行演示。
让我们首先创建包含一个数字响应 (
mpg
) 和 3 个分类预测变量 (cyl
、gear
、carb
的示例数据).library(tidyverse) df <- mtcars %>% select(mpg, cyl, gear, carb) %>% mutate_at(vars(-mpg), as.factor)
然后我们在观察训练数据集上训练模型,这些训练数据集只有
cyl
和gear
的一些(但不是全部)因子水平。df.train <- df %>% filter(cyl %in% c(4, 6) & gear %in% c(3, 4))
我们拟合一个简单的线性模型。
fit <- lm(mpg ~ ., data = df.train)
我们现在定义一个自定义函数,将
newdata
拆分为具有 (1) 匹配factor
水平的观察结果,我们可以predict
对其做出响应,以及 ( 2) "novel" 水平,我们 returnNA
作为回应。factor
所有分类变量的水平存储在fit$xlevels
中作为list
。我们使用purrr::imap
和purrr::reduce(..., intersect)
来确定newdata
中具有匹配factor
水平的那些观察的行索引。my.predict <- function(fit, newdata) { lvls <- fit$xlevels idx <- reduce(imap(lvls, ~which(newdata[, .y] %in% .x)), intersect) res <- rep(NA, nrow(newdata)) res[idx] <- predict(fit, newdata = newdata[idx, ]) return(res) }
我们在完整的
df
数据集上确认结果:df$pred <- my.predict(fit, df) df # mpg cyl gear carb pred #1 21.0 6 4 4 19.75 #2 21.0 6 4 4 19.75 #3 22.8 4 4 1 29.10 #4 21.4 6 3 1 19.75 #5 18.7 8 3 2 NA #6 18.1 6 3 1 19.75 #7 14.3 8 3 4 NA #8 24.4 4 4 2 24.75 #9 22.8 4 4 2 24.75 #10 19.2 6 4 4 19.75 #11 17.8 6 4 4 19.75 #12 16.4 8 3 3 NA #13 17.3 8 3 3 NA #14 15.2 8 3 3 NA #15 10.4 8 3 4 NA #16 10.4 8 3 4 NA #17 14.7 8 3 4 NA #18 32.4 4 4 1 29.10 #19 30.4 4 4 2 24.75 #20 33.9 4 4 1 29.10 #21 21.5 4 3 1 21.50 #22 15.5 8 3 2 NA #23 15.2 8 3 2 NA #24 13.3 8 3 4 NA #25 19.2 8 3 2 NA #26 27.3 4 4 1 29.10 #27 26.0 4 5 2 NA #28 30.4 4 5 2 NA #29 15.8 8 5 4 NA #30 19.7 6 5 6 NA #31 15.0 8 5 8 NA #32 21.4 4 4 2 24.75