首页 > 解决方案 > na.fail.default(list(Fe = c(568L, 437L, 599L, 1016L, 670L, 1951L, : 对象中的缺失值

问题描述

我正在尝试使用具有 XRF 光谱的 Fe 浓度运行 PLSR 模型。光谱矩阵包含一些零值。在弹出错误消息之前我使用的代码如下:

#------------------------------------------------------------------------
dataset<-data.frame(cbind(chem_properties$Fe, xrf_spectra))
names(dataset)[1]<-"Fe"
summary(dataset$Fe)
dim(dataset)
plot(dataset$Fe)

#######################################
## Building calibration model

# Dataset partitioning
set.seed(100)
pls_Fe <- createDataPartition(dataset$Fe, p = 0.7, list = FALSE)
training <- dataset[pls_Fe,]
testing <- dataset[-pls_Fe,]
summary(training$Fe)
summary(testing$Fe)

# =================================================
# Model 

tc <- trainControl(method = "repeatedcv", number = 10, repeats = 5)
tg <- data.frame(ncomp = seq(2, 15, by =1))
pls_rcv <- train(Fe~., 
                 data = training,
                 preProcess = c("center", "scale"),
                 method = "pls",
                 tuneGrid = tg,
                 trControl = tc) 

#----------------------------------------------------------------------------------

每当我运行最后一行(即 pls_rcv)时,都会显示此错误消息;

...... na.fail.default(list(Fe = c(568L, 437L, 599L, 1016L, 670L, 1951L, : 对象中的缺失值...... …………

尽管我的问题与之前提出的一些问题相似,但在这些情况下我已经尝试了一些建议的解决方案,但似乎都没有奏效。也许我宁愿做错事。

建议之一是在整个数据框上使用 na.exclude() 。收到您的反馈,我将不胜感激。

标签: r

解决方案


所以这是答案的第一遍,但没有在数据的子样本上达到峰值,这是我可以给出的要点。

首先,我们可以设置一些假数据并添加一些缺失的案例来解决第一个问题。

# Some fake data
dat <- mtcars

# Now lets add some missing data

dat[sample(x = 1:nrow(dat), size = 5),
    sample(x = 1:ncol(dat), size = 5)] <- NA

现在我们查看我们的数据,我们看到我们有一些缺失值:(该函数计算每列缺失的单元格,然后将输出转换为数据框以便于呈现)

as.data.frame(lapply(dat, function(x) sum(is.na(x))))

#>  mpg cyl disp hp drat wt qsec vs am gear carb
#> 1   0   5    0  0    5  5    0  5  5    0    0

如果我们知道我们不能有缺失值,那么我们可以使用该complete.cases函数只保留那些没有任何 NA 的行。

dat_complete <- dat[complete.cases(dat),]

这会删除一些记录(在我的情况下为 5)

nrow(dat) -nrow(dat_complete)
#> [1] 5

另外:如果删除丢失的数据是有问题的(例如,从这些数据中丢弃信息可能会使您的估计产生偏差。也许数据不是完全随机丢失,或者存在已知的仪器故障),有许多插补和联合估计的方法的缺失值。

第二个问题处理不包含所有因素的拆分。

例如,如果我要向我的数据集添加一个因子并生成分区,那么查看我是否在训练数据中捕获了该因子很重要。

# Add factor (note D is a rare letter)
library(caret)
dat_complete$my_factor <- factor(sample(x = letters[1:4], 
                                        size = nrow(dat_complete),
                                        prob = c(.7,.2,.15,.05), replace = T))

pls_Fe <- createDataPartition(dat_complete$mpg, p = 0.7, list = FALSE)
training <- dat_complete[pls_Fe,]
testing <- dat_complete[-pls_Fe,]


当我查看我的测试和训练数据时,我发现虽然我的测试数据有一个“D”,但我的训练数据没有。

table(training$my_factor)
#> a  b  c 
#> 14  6  0 
table(testing$my_factor)
#> a b c 
#> 5 1 1

模型无法在新的因子水平上可靠地预测(当然,一般来说,还有更多方法)。

如何解决这个问题?如果在上下文中有意义,您始终可以将因子转换为数字(增加偏差,但允许您的模型工作)。你可能需要放弃你的分裂(而不是 70% 的训练,做 60%,看看你是否捕获了一些低发生率的样本)。如果预测变量不相关,则将它们从考虑中删除。此外,鉴于这是 PLS,您还可以尝试 one-hot 编码。这会将因子列拆分为 n-1 列,其中 1 或 0 表示因子表示。在完整的数据集上执行此操作(仅当您知道您将始终观察因素时,例如该值只能采用一个类别)。

dumz <- dummyVars(~my_factor, data = dat_complete)

dat_dummies <- cbind(dat_complete, predict(dumz, dat_complete))

dat_dummies <- dat_dummies[,names(dat_dummies) !="my_factor"]

pls_Fe <- createDataPartition(dat_dummies$mpg, p = 0.7, list = FALSE)


training <- dat_dummies[pls_Fe,]
testing <- dat_dummies[-pls_Fe,]


推荐阅读