在R中如何强制`table`函数包含两个数组中的所有因子?

3

我正在使用以下R代码生成混淆矩阵,将一些数据的真实标签与神经网络的输出进行比较。

t <- table(as.factor(test.labels), as.factor(nnetpredict))

然而,有时神经网络不会预测某个特定类别的任何结果,因此表格就不是正方形的(例如,在测试标签要素中有5个级别,但在nnetpredict要素中只有3个级别)。 我想通过添加必要的任何要素级别并将它们的计数设置为零来使表格成为正方形。
我应该如何做呢?
示例:
> table(as.factor(a), as.factor(b))

    1 2 3 4 5 6 7 8 9 10
  1 1 0 0 0 0 0 0 1 0  0
  2 0 1 0 0 0 0 0 0 1  0
  3 0 0 1 0 0 0 0 0 0  1
  4 0 0 0 1 0 0 0 0 0  0
  5 0 0 0 0 1 0 0 0 0  0
  6 0 0 0 0 0 1 0 0 0  0
  7 0 0 0 0 0 0 1 0 0  0

您可以在上面的表格中看到,有7行但是10列,因为因素a只有7个水平,而因素b有10个水平。我想要做的是用零填充表格,使行标签和列标签相同,并且矩阵是正方形的。从上面的例子可以看出,这将产生以下结果:
    1 2 3 4 5 6 7 8 9 10
  1  1 0 0 0 0 0 0 1 0  0
  2  0 1 0 0 0 0 0 0 1  0
  3  0 0 1 0 0 0 0 0 0  1
  4  0 0 0 1 0 0 0 0 0  0
  5  0 0 0 0 1 0 0 0 0  0
  6  0 0 0 0 0 1 0 0 0  0
  7  0 0 0 0 0 0 1 0 0  0
  8  0 0 0 0 0 0 0 0 0  0
  9  0 0 0 0 0 0 0 0 0  0
  10 0 0 0 0 0 0 0 0 0  0

我需要这样做的原因有两个:

  • 用于向用户显示/在报告中展示
  • 这样我就可以使用函数计算Kappa统计量,该函数需要按此格式格式化的表格(方形,行和列标签相同)

不要将对象命名为t,以保留转置(t())函数的功能。 - Chase
谢谢 - 我没有意识到! - robintw
我明白你现在需要做什么了,这比我最初想象的要复杂一些。我稍后会考虑一下。你的因子总是有重叠的水平吗?这些因子是否总是按相同顺序排序? - Chase
谢谢 - 非常好。在这种情况下,我将有一个因子,它将始终具有数字0-9,并且另一个因子将始终是该数字的某个子集(大多数情况下也将是完整的0-9,但当它不是时,我需要解决它)。它们应该始终按升序排序,至少表命令似乎是这样做的。 - robintw
1个回答

5

编辑 - 第二轮处理问题中的额外细节。我删除了我的第一个答案,因为它已经不再相关。

这种方法已经产生了我所给出的测试用例所期望的输出,但是我强烈建议在您的真实数据上进行彻底的测试。这里的方法是找到表格输入的两个输入的完整级别列表,并将该完整列表设置为生成表格之前的级别。

squareTable <- function(x,y) {
    x <- factor(x)
    y <- factor(y)

    commonLevels <- sort(unique(c(levels(x), levels(y))))

    x <- factor(x, levels = commonLevels)
    y <- factor(y, levels = commonLevels)

    table(x,y)

}

两个测试用例:

> #Test case 1
> set.seed(1)
> x <- factor(sample(0:9, 100, TRUE))
> y <- factor(sample(3:7, 100, TRUE))
> 
> table(x,y)
   y
x   3 4 5 6 7
  0 2 1 3 1 0
  1 1 0 2 3 0
  2 1 0 3 4 3
  3 0 3 6 3 2
  4 4 4 3 2 1
  5 2 2 0 1 0
  6 1 2 3 2 3
  7 3 3 3 4 2
  8 0 4 1 2 4
  9 2 1 0 0 3
> squareTable(x,y)
   y
x   0 1 2 3 4 5 6 7 8 9
  0 0 0 0 2 1 3 1 0 0 0
  1 0 0 0 1 0 2 3 0 0 0
  2 0 0 0 1 0 3 4 3 0 0
  3 0 0 0 0 3 6 3 2 0 0
  4 0 0 0 4 4 3 2 1 0 0
  5 0 0 0 2 2 0 1 0 0 0
  6 0 0 0 1 2 3 2 3 0 0
  7 0 0 0 3 3 3 4 2 0 0
  8 0 0 0 0 4 1 2 4 0 0
  9 0 0 0 2 1 0 0 3 0 0
> squareTable(y,x)
   y
x   0 1 2 3 4 5 6 7 8 9
  0 0 0 0 0 0 0 0 0 0 0
  1 0 0 0 0 0 0 0 0 0 0
  2 0 0 0 0 0 0 0 0 0 0
  3 2 1 1 0 4 2 1 3 0 2
  4 1 0 0 3 4 2 2 3 4 1
  5 3 2 3 6 3 0 3 3 1 0
  6 1 3 4 3 2 1 2 4 2 0
  7 0 0 3 2 1 0 3 2 4 3
  8 0 0 0 0 0 0 0 0 0 0
  9 0 0 0 0 0 0 0 0 0 0
> 
> #Test case 2
> set.seed(1)
> xx <- factor(sample(0:2, 100, TRUE))
> yy <- factor(sample(3:5, 100, TRUE))
> 
> table(xx,yy)
   yy
xx   3  4  5
  0  4 14  9
  1 14 15  9
  2 11 11 13
> squareTable(xx,yy)
   y
x    0  1  2  3  4  5
  0  0  0  0  4 14  9
  1  0  0  0 14 15  9
  2  0  0  0 11 11 13
  3  0  0  0  0  0  0
  4  0  0  0  0  0  0
  5  0  0  0  0  0  0
> squareTable(yy,xx)
   y
x    0  1  2  3  4  5
  0  0  0  0  0  0  0
  1  0  0  0  0  0  0
  2  0  0  0  0  0  0
  3  4 14 11  0  0  0
  4 14 15 11  0  0  0
  5  9  9 13  0  0  0

@robintw - 更新了答案,我认为我们现在应该在正确的轨道上了。让我知道吧!-C - Chase
谢谢 - 看起来就是我想要的。唯一的问题是有时我会出现错误,显示 Error in t < squareTable(test.labels, nnetpredict) : non-conformable arrays。我不知道为什么会发生这种情况 - 当它发生时,我无法看到数据上有任何不同之处!有什么想法吗? - robintw
1
@robintw - 这很奇怪 - 这个错误通常意味着您正在尝试执行无法相乘的乘法或矩阵等操作...这在这里并不是非常直观。听起来它至少有时候可以正常工作?我建议您检查一下str(),找出一个能够正常工作的测试用例和一个不能正常工作的测试用例之间的区别。如果可能的话,请使用dput()将工作和不工作的示例内容放入问题中。 - Chase
谢谢。我已经找到了一个可行的和一个不可行的例子,我将它们放在gist中:https://gist.github.com/905603,因为它们对于这里的问题来说有点太长了。 - robintw
@robintw - 嗯,这两个例子在我的电脑上都没有问题。我认为 as.factor() 部分可能是多余的,因为该函数会将所有内容转换为因子 - 但是无论哪种方式,代码在我的机器上都可以正常执行。您是否将其用作更大功能的一部分?错误可能来自其他地方吗?我想知道是否存在作用域问题。也许关闭 R 并重新启动一个新会话?只是随口说说... - Chase
@Chase - 我似乎现在已经成功解决了它。我重命名了一些变量,重新排列了一些代码,并且整理了一下,现在看起来已经修复了任何问题。感谢您的帮助 :) - robintw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接