使用循环在 R 中创建多个混淆矩阵
Create multiple confusion matrices in R using loops
我正在尝试从一个数据帧创建多个混淆矩阵,每个矩阵都是根据数据帧中的不同条件生成的。
所以对于下面的数据框,我想要一个混淆矩阵,用于 Value = 1
、Value = 2
、Value =3
observed predicted Value
1 1 1
0 1 1
1 0 2
0 0 2
1 1 3
0 0 3
并查看如下结果:
Value Sensitivity Specificity PPV NPV
1 .96 .71 .84 .95
2 .89 .63 .30 .45
3 .88 .95 .28 .80
这是我用可重现的例子尝试过的。我正在尝试编写一个循环来查看每一行,确定是否 Age = 1
,然后从预测列和观察列中提取值以生成混淆矩阵。然后我手动从混淆矩阵中提取值,写出 sen、spec、ppv 和 npv,并尝试将所有矩阵组合在一起。然后循环再次从 Age = 2
.
开始
data(scat)
df<-scat %>% transmute(observed=ifelse(Site=="YOLA","case", "control"), predicted=ifelse(Location=="edge","case", "control"),Age)
x<-1 #evaluate at ages 1 through 5
for (i in dim(df)[1]) { #for every row in df
while(x<6) { #loop stops at Age=5
if(x=df$Age) {
q<-confusionMatrix(data = df$predicted, reference = df$observed, positive = "case")
sensitivity = q$table[1,1]/(q$table[1,1]+q$table[2,1])
specificity = q$table[2,2]/(q$table[2,2]+q$table[1,2])
ppv = q$table[1,1]/(q$table[1,1]+q$table[1,2])
npv = q$table[2,2]/(q$table[2,2]+q$table[2,1])
matrix(c(sensitivity, specificity, ppv, npv),ncol=4,byrow=TRUE)
}
}
x <- x + 1 #confusion matrix at next Age value
}
final<- rbind(matrix) #combine all the matrices together
但是,这个循环完全不起作用。我不确定错误在哪里。
您的代码可以简化,并且可以像这样实现所需的输出:
library(caret)
library(dplyr)
data(scat)
df <- scat %>%
transmute(observed = factor(ifelse(Site == "YOLA","case", "control")),
predicted = factor(ifelse(Location == "edge","case", "control")),
Age)
final <- t(sapply(sort(unique(df$Age)), function(i) {
q <- confusionMatrix(data = df$predicted[df$Age == i],
reference = df$observed[df$Age == i],
positive = "case")$table
c(sensitivity = q[1, 1] / (q[1, 1] + q[2, 1]),
specificity = q[2, 2] / (q[2, 2] + q[1, 2]),
ppv = q[1, 1] / (q[1, 1] + q[1, 2]),
npv = q[2, 2] / (q[2, 2] + q[2, 1]))
}))
导致
final
#> sensitivity specificity ppv npv
#> [1,] 0.0 0.5625000 0.00000000 0.8181818
#> [2,] 0.0 1.0000000 NaN 0.8000000
#> [3,] 0.2 0.5882353 0.06666667 0.8333333
#> [4,] 0.0 0.6923077 0.00000000 0.6923077
#> [5,] 0.5 0.6400000 0.25000000 0.8421053
但是,很高兴知道为什么您自己的代码不起作用,所以这里有一些问题可能对您有所帮助:
- 对于
confusionMatrix
,您需要因子列而不是字符列
- 您在
df
的行中递增,但您需要对每个唯一年龄进行一次迭代,而不是数据框中的每一行。
- 你增加
x
的行发生在 while
循环之外,所以 x
永远不会增加并且循环永远不会终止,所以控制台只是挂起。
- 您正在做
if(x = df$Age)
,但您需要 ==
来测试相等性。
- 无论如何比较
x
和df$Age
是没有意义的,因为x
是长度1而df$Age
是一个长向量。
- 你每次都做
q$table
会有不必要的重复。你可以让 q
等于 q$table
来让你的代码更易读并且更不容易出错。
- 你在循环结束时调用了
matrix
,但你没有将它存储在任何地方,所以整个循环实际上没有做任何事情。
- 您正在尝试
rbind
最后一行中名为 matrix
的对象
- 数学运算符、逗号和变量之间缺少空格会降低代码的可读性和调试难度。我不只是说这是一种文体观点;这是我经常在 SO 上看到的主要错误来源。
我正在尝试从一个数据帧创建多个混淆矩阵,每个矩阵都是根据数据帧中的不同条件生成的。
所以对于下面的数据框,我想要一个混淆矩阵,用于 Value = 1
、Value = 2
、Value =3
observed predicted Value
1 1 1
0 1 1
1 0 2
0 0 2
1 1 3
0 0 3
并查看如下结果:
Value Sensitivity Specificity PPV NPV
1 .96 .71 .84 .95
2 .89 .63 .30 .45
3 .88 .95 .28 .80
这是我用可重现的例子尝试过的。我正在尝试编写一个循环来查看每一行,确定是否 Age = 1
,然后从预测列和观察列中提取值以生成混淆矩阵。然后我手动从混淆矩阵中提取值,写出 sen、spec、ppv 和 npv,并尝试将所有矩阵组合在一起。然后循环再次从 Age = 2
.
data(scat)
df<-scat %>% transmute(observed=ifelse(Site=="YOLA","case", "control"), predicted=ifelse(Location=="edge","case", "control"),Age)
x<-1 #evaluate at ages 1 through 5
for (i in dim(df)[1]) { #for every row in df
while(x<6) { #loop stops at Age=5
if(x=df$Age) {
q<-confusionMatrix(data = df$predicted, reference = df$observed, positive = "case")
sensitivity = q$table[1,1]/(q$table[1,1]+q$table[2,1])
specificity = q$table[2,2]/(q$table[2,2]+q$table[1,2])
ppv = q$table[1,1]/(q$table[1,1]+q$table[1,2])
npv = q$table[2,2]/(q$table[2,2]+q$table[2,1])
matrix(c(sensitivity, specificity, ppv, npv),ncol=4,byrow=TRUE)
}
}
x <- x + 1 #confusion matrix at next Age value
}
final<- rbind(matrix) #combine all the matrices together
但是,这个循环完全不起作用。我不确定错误在哪里。
您的代码可以简化,并且可以像这样实现所需的输出:
library(caret)
library(dplyr)
data(scat)
df <- scat %>%
transmute(observed = factor(ifelse(Site == "YOLA","case", "control")),
predicted = factor(ifelse(Location == "edge","case", "control")),
Age)
final <- t(sapply(sort(unique(df$Age)), function(i) {
q <- confusionMatrix(data = df$predicted[df$Age == i],
reference = df$observed[df$Age == i],
positive = "case")$table
c(sensitivity = q[1, 1] / (q[1, 1] + q[2, 1]),
specificity = q[2, 2] / (q[2, 2] + q[1, 2]),
ppv = q[1, 1] / (q[1, 1] + q[1, 2]),
npv = q[2, 2] / (q[2, 2] + q[2, 1]))
}))
导致
final
#> sensitivity specificity ppv npv
#> [1,] 0.0 0.5625000 0.00000000 0.8181818
#> [2,] 0.0 1.0000000 NaN 0.8000000
#> [3,] 0.2 0.5882353 0.06666667 0.8333333
#> [4,] 0.0 0.6923077 0.00000000 0.6923077
#> [5,] 0.5 0.6400000 0.25000000 0.8421053
但是,很高兴知道为什么您自己的代码不起作用,所以这里有一些问题可能对您有所帮助:
- 对于
confusionMatrix
,您需要因子列而不是字符列
- 您在
df
的行中递增,但您需要对每个唯一年龄进行一次迭代,而不是数据框中的每一行。 - 你增加
x
的行发生在while
循环之外,所以x
永远不会增加并且循环永远不会终止,所以控制台只是挂起。 - 您正在做
if(x = df$Age)
,但您需要==
来测试相等性。 - 无论如何比较
x
和df$Age
是没有意义的,因为x
是长度1而df$Age
是一个长向量。 - 你每次都做
q$table
会有不必要的重复。你可以让q
等于q$table
来让你的代码更易读并且更不容易出错。 - 你在循环结束时调用了
matrix
,但你没有将它存储在任何地方,所以整个循环实际上没有做任何事情。 - 您正在尝试
rbind
最后一行中名为matrix
的对象 - 数学运算符、逗号和变量之间缺少空格会降低代码的可读性和调试难度。我不只是说这是一种文体观点;这是我经常在 SO 上看到的主要错误来源。