我正在为一个大型样本点数据集创建混淆矩阵,并需要使用R包caret
中的confusionMatrix
函数对它们进行循环(我使用的是输出中的准确性指标,即我不能仅使用table
)。每个样本点集应该有三个类/因子,即我应该有3×3的表格,然而一些参考和预测数据包含少于两个类,或者类别不重叠,例如:
Class A B Class C A 8 2 A 3 B 1 0 C 1 7* 列 = 参考数据,行 = 预测数据
我需要相同数量的类/因子来运行confusionMatrix
,所以我想做的是有条件地用零替换缺失的因子,像这样:
Class A B C Class A B C A 8 2 0 A 0 0 3 B 1 0 0 B 0 0 0 C 1 7 0 C 0 0 0
我使用的预测/参考数据是数值列表的值,所以我不会在这里重现它们;对于我上面提供的示例,您可以将其视为仅是一个向量,如下所示:
predicted.data[1] = A A A A A A A A A A B C C C C C C C Creference.data[1] = A A A A A A A A A A B B B B B B B B Bpredicted.data[2] = A A Areference.data[2] = C C C
我尝试创建某种条件if
语句,类似于:
tab <- table(predicted.data, reference.data) if(nrow(tab) != ncol(tab){ classes <- c("A","B","C") missing <- setdiff(classes,names(tab)) ... ... }# 显然会将实际数据放入循环/索引中
但我似乎无法按我想要的方式使其工作。有什么想法吗?
编辑:我使用的实际数据示例(通过栅格/形状文件)和错误消息;数据长度相同,但没有参考数据被分类为’2’:
> mask.vals[[4]] [1] 0 4 0 0 0 2 4 0 4 0 4 0 0 0 0 0 4 0 4 2 0 0 0 0 0 0 0 4 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 2 2 0 2 0 4 0 0 4 2 0 0 4 0 0 0 0 0 0 0 2 0 2 0 2 4 0 4 [72] 4 0 0 0 0 4 4 0 0 0 0 0 0 0 4 0 0 0 0 4 4 4 4 0 4 4 4 4 4 0 4 4 4 0 4 0 0 4 4 4 4 4 4> ref.data[[4]]@data$CLASS_ID [1] 0 4 4 4 4 4 4 4 4 4 4 4 4 4 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 [72] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4> confusionMatrix(data = mask.vals[[4]], reference = ref.data[[4]]@data$CLASS_ID)Error in confusionMatrix.default(data = mask.vals[[4]], reference = ref.data[[4]]@data$CLASS_ID) : the data cannot have more levels than the reference
即需要从这个:
> table(mask.vals[[4]], ref.data[[4]]@data$CLASS_ID) 0 4 0 2 67 2 0 9 4 0 36
变为这个:
0 2 4 0 2 0 67 2 0 0 9 4 0 0 36
即使我为数据定义了三个级别(例如levels(ref.data[[4]]@data$CLASS_ID) <- c("0","2","4")
或factor(ref.data[[4]]@data$CLASS_ID, levels = c("0","2","4")
),这个错误仍然存在…
回答:
caret
包中的confusionMatrix
函数会返回一个n x n的表格,无论参考和/或预测向量中是否缺少某些级别。我想知道你是如何设法得到一个混淆矩阵,其中一些参考数据列缺失的。例如,使用内置的iris
数据框架:
library(caret)set.seed(2)dat = data.frame(ref=iris$Species, pred=sample(iris$Species))# 从参考数据中移除两个级别dat1 = dat[dat$ref=="setosa", ]# 获取混淆矩阵cm1 = confusionMatrix(dat1$pred, dat1$ref)cm1$table
ReferencePrediction setosa versicolor virginica setosa 15 0 0 versicolor 15 0 0 virginica 20 0 0
# 参考和预测之间没有重叠dat2 = dat[dat$ref=="setosa" & dat$pred=="versicolor", ]# 获取混淆矩阵cm2 = confusionMatrix(dat2$pred, dat2$ref)cm2$table
ReferencePrediction setosa versicolor virginica setosa 0 0 0 versicolor 15 0 0 virginica 0 0 0
在上面的示例中,ref
和pred
列都被编码为具有Species
原始三个级别的因子。我们可以重新编码它们以删除空级别:
dat2$ref = droplevels(dat2$ref)dat2$pred = droplevels(dat2$pred)
您可以看到每个列中只有一个因子级别存在:
lapply(dat2, levels)
$ref [1] "setosa"$pred [1] "versicolor"
但如果您运行confusionMatrix
,现在会抛出错误,因为两个向量的级别之间没有重叠:
cm3 = confusionMatrix(dat2$pred, dat2$ref)
Error in confusionMatrix.default(dat2$pred, dat2$ref) : The data must contain some levels that overlap the reference.
更新: 如果您在参考向量和预测向量中设置相同的因子级别,confusionMatrix
将正常工作。您已经更新了问题,但它仍然不可重现,因此很难确定您的工作流程中哪里出了问题。现在,这里有一个与您在问题中显示的类似且在设置公共因子级别后按预期工作的示例。
library(caret)set.seed(2)mask.vals = sample(c(0,2,4), 100, replace=TRUE)ref.data = rep(4,100)cm = confusionMatrix(mask.vals, ref.data)
Error in confusionMatrix.default(mask.vals, ref.data) : the data cannot have more levels than the reference
mask.vals = factor(mask.vals, levels=c(0,2,4))ref.data = factor(ref.data, levels=c(0,2,4))cm = confusionMatrix(mask.vals, ref.data) cm$table
ReferencePrediction 0 2 4 0 0 0 35 2 0 0 31 4 0 0 34