我正在尝试从二进制矩阵中删除“单例”。在这里,单例是指在它们出现的行和列中唯一的“1”值的元素。例如,给定以下矩阵:
> matrix(c(0,1,0,1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1), nrow=6)
[,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 0 1 0 0 0 0 0
[2,] 1 0 1 0 0 0 0
[3,] 0 0 0 1 0 0 0
[4,] 1 1 0 0 0 0 0
[5,] 0 0 0 0 1 1 1
[6,] 0 0 0 0 1 0 1
...我想删除所有第 3 行(如果可能,删除所有第 4 列),因为 [3,4] 中的 1 是该行/列组合中唯一的 1。 [1,2] 很好,因为 [,2] 列中还有其他 1;同样,[2,3] 很好,因为在第 [2,] 行还有其他 1。任何帮助将不胜感激 - 谢谢!
最佳答案
您首先要查找哪些行和列是单例,然后检查是否有共享索引的单例行和列对。这是完成此任务的一小段代码:
foo <- matrix(c(0,1,0,...))
singRows <- which(rowSums(foo) == 1)
singCols <- which(colSums(foo) == 1)
singCombinations <- expand.grid(singRows, singCols)
singPairs <- singCombinations[apply(singCombinations, 1,
function(x) which(foo[x[1],] == 1) == x[2]),]
noSingFoo <- foo[-unique(singPairs[,1]), -unique(singPairs[,2])]
使用许多 sinlgeton ros 或列,您可能需要提高效率,但它可以完成工作。
更新:这是我知道可以完成的更有效的版本。这样您只循环遍历行(或列,如果需要)而不是所有组合。因此,对于具有许多单例行/列的矩阵,效率要高得多。
## starting with foo and singRows as before
singPairRows <- singRows[sapply(singRows, function(singRow)
sum(foo[,foo[singRow,] == 1]) == 1)]
singPairs <- sapply(singPairRows, function(singRow)
c(singRow, which(foo[singRow,] == 1)))
noSingFoo <- foo[-singPairs[1,], -singPairs[2,]]
更新 2:我已经使用 rbenchmark 包比较了这两种方法(mine=nonsparse 和 @Chris's=sparse)。我使用了一系列矩阵大小(从 10 到 1000 行/列;仅限方阵)和稀疏级别(从每行/列 0.1 到 5 个非零条目)。性能的相对水平显示在下面的热图中。同等性能(运行时间的 log2 比率)用白色表示,使用稀疏方法更快是红色,使用非稀疏方法更快是蓝色。请注意,我没有在性能计算中包括到稀疏矩阵的转换,因此这会为稀疏方法增加一些时间。只是觉得值得花点功夫看看这个边界在哪里。
关于从二进制矩阵中删除只有一个元素的行/列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30923377/