r - 将fusionMatrix()应用于R中拆分列表的元素

标签 r matrix element lapply

我正在寻找一种解决方案,将 {caret} 中的 fusionMatrix() 函数应用到拆分列表的特定元素。我有 3 个组,每个组有 10 个实际值观察值和 3 个预测值列。

library(caret)
set.seed(10)
dat <- data.frame(Group = c(rep(1, 10), rep(2, 10), rep(3, 10)), Actual = round(runif(30, 0, 1)),
              Preds1 = round(runif(30, 0, 1)), Preds2 = round(runif(30, 0, 1)), Preds3 = round(runif(30, 0, 1)))

> dat
   Group Actual Preds1 Preds2 Preds3
1      1      1      1      0      0
2      1      0      0      0      1
3      1      0      0      0      1
4      1      1      1      0      1
...........
27     3      1      0      1      0
28     3      0      0      0      1
29     3      1      0      0      1
30     3      0      1      0      1

最终的解决方案应按组、每个 Preds 列创建混淆矩阵。我将需要实际的混淆矩阵表,但最终需要提取 $overall 和 $byClass 元素,并最终得到如下所示的内容。

> conf_matrix
$Preds1
      Accuracy  Sensitivity  Specificity
 [1,] 0.73      0.8          0.6            
 [2,] 0.93      0.91         1              
 [3,] 0.87      0.83         1              
 [4,] 0.8       0.82         0.75
...............
[27,] 0.8       0.82         0.75           
[28,] 0.58      0.67         0.5            
[29,] 1         0.67         1              
[30,] 1         0            1

$Preds2
      Accuracy  Sensitivity  Specificity
 [1,] 0.73      0.8          0.6            
 [2,] 0.93      0.91         1              
 [3,] 0.87      0.83         1              
 [4,] 0.8       0.82         0.75    
...............
[27,] 0.8       0.82         0.75           
[28,] 0.58      0.67         0.5            
[29,] 1         0.67         1              
[30,] 1         0            1

$Preds3
...............

我已经尝试了下面的脚本,但在尝试按每个组中的 Preds 列进行二级索引时不断遇到问题。我相信这与我的嵌套 lapply 以及我的索引方式有关,因为当我分解代码并一次逐步执行它时,这会起作用。

我也尝试使用 table() 手动执行此操作,但是放弃了该方法,因为它不能像使用 fusionMatrix() 那样给我一致的结果。

lapply(seq_along(split(dat[3:5], list(dat$Group))), function(x) {
    x_temp <- split(dat[3:5], list(dat$Group))[[x]]
    lapply(seq_along(x_temp), function(x2) {
        x_temp <- x_temp[[x2]]
        lapply(seq_along(split(dat[2], list(dat$Group))), function(y) {
            y_temp <- split(dat[2], list(dat$Group))[[y]]
            lapply(seq_along(y_temp), function(y2) {
                y_temp <- y_temp[[y2]]
                confusionMatrix(x_temp, y_temp)
            })
        })
    })
})

我可能偏离了基地,所以我愿意接受所有建议和评论。

最佳答案

我不明白最终结果,但混淆矩阵将通过以下方式获得。

library(caret)
set.seed(10)
dat <- data.frame(Group = c(rep(1, 10), rep(2, 10), rep(3, 10)), Actual = round(runif(30, 0, 1)),
                  Preds1 = round(runif(30, 0, 1)), Preds2 = round(runif(30, 0, 1)), Preds3 = round(runif(30, 0, 1)))
dat[] <- lapply(dat, as.factor)

# split by group
dats <- split(dat[,-1], dat$Group)

cm <- do.call(c, lapply(dats, function(x) {
  actual <- x[, 1]
  lapply(x[, 2:4], function(y) {
    confusionMatrix(actual, unlist(y))$table
  })
}))
cm[1:3]
$`1.Preds1`
Reference
Prediction 0 1
0 3 4
1 0 3

$`1.Preds2`
Reference
Prediction 0 1
0 4 3
1 3 0

$`1.Preds3`
Reference
Prediction 0 1
0 3 4
1 1 2

@布莱恩

在链接 ( What's the difference between lapply and do.call in R? ) 中,我发现 Paul Hiemstra 的答案非常简单。

-lapply类似于 map , do.call不是。 lapply将函数应用于列表的所有元素,do.call调用一个函数,其中所有函数参数都在列表中。所以对于n元素列表,lapplyn函数调用,以及do.call刚刚one函数调用。所以do.calllapply 有很大不同.

在示例中,

dats具有三个元素 - 1 , 23

dats <- split(dat[,-1], dat$Group)
dats[1]
$`1`
Actual Preds1 Preds2 Preds3
1       1      1      0      0
2       0      0      0      1
3       0      0      0      1
4       1      1      0      1
5       0      0      1      0
6       0      1      1      1
7       0      1      1      0
8       0      1      0      1
9       1      1      0      1
10      0      1      0      0

下面是双循环,第一个循环应用于 1 , 23第二个循环到 Preds1、Preds2 和 Preds3。因此,lapply() 生成的列表单独生成一个嵌套列表,如下所示。

lapply(dats, function(x) {
  actual <- x[, 1]
  lapply(x[, 2:4], function(y) {
    confusionMatrix(actual, unlist(y))$table
  })
})[1]
$`1`
$`1`$Preds1
Reference
Prediction 0 1
0 3 4
1 0 3

$`1`$Preds2
Reference
Prediction 0 1
0 4 3
1 3 0

$`1`$Preds3
Reference
Prediction 0 1
0 3 4
1 1 2

然而,上面的内容稍后使用起来并不容易,因为需要另一个双循环才能访问每个混淆矩阵。它被简化为 do.call() 。第一个参数c是一个函数,它的作用是 c(dats$ 1 $Preds1, dats$ 1 $Preds2, dats$ 1 $Preds2 ...)以便将结构简化为可以通过单个循环访问。通常我倾向于使用 do.call()当需要更改列表的结构时。

do.call(c, lapply(dats, function(x) {
  actual <- x[, 1]
  lapply(x[, 2:4], function(y) {
    confusionMatrix(actual, unlist(y))$table
  })
}))[1:3]
$`1.Preds1`
Reference
Prediction 0 1
0 3 4
1 0 3

$`1.Preds2`
Reference
Prediction 0 1
0 4 3
1 3 0

$`1.Preds3`
Reference
Prediction 0 1
0 3 4
1 1 2

关于r - 将fusionMatrix()应用于R中拆分列表的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29902946/

相关文章:

matrix - 在 rmarkdown 中写一个分区矩阵

python - 有效地将大量 SciPy 稀疏矩阵条目设置为零

python - 将列表中所有元素相加但不包括第一个偶数的函数

javascript - 带有基于输入值的前缀名称的 jQuery addClass

R:VGAM 中的不兼容尺寸错误 vglm 函数

r - sapply 和 apply 使用 is.character() 给出不同的结果

r - r 中具有列约束的唯一行

java - LWJGL 矩阵堆栈意外行为

c++ - 如何获取数组元素的地址?

R:调整多次出现的情况的值