![](/img/trans.png)
[英]R, Trying to transform a vector of integer to a specific binary Matrix
[英]Transform binary vector to binary matrix
我有一个二进制向量,可以保存某些观察事件是否发生的信息:
v <- c(0,1,1,0)
我想要实现的是一个矩阵,其中包含该向量中所有双变量观测对的信息。 也就是说,如果两个观察值都为0或两个都在此向量v中有1,则它们应该在矩阵中得到1。 如果一个有0而另一个有1,那么它们应该得到0。
因此,目标是这个矩阵:
[,1] [,2] [,3] [,4]
[1,] 0 0 0 1
[2,] 0 0 1 0
[3,] 0 1 0 0
[4,] 1 0 0 0
主对角线是0还是1对我来说无关紧要。
是否有一种有效且简单的方法来实现这一点,不需要if
语句和for
循环的组合? v
可能有相当大的规模。
谢谢!
我们可以使用outer
out <- outer(v, v, `==`)
diag(out) <- 0L # as you don't want to compare each element to itself
out
# [,1] [,2] [,3] [,4]
#[1,] 0 0 0 1
#[2,] 0 0 1 0
#[3,] 0 1 0 0
#[4,] 1 0 0 0
expand.grid
另一个选项是创建v
与自身的成对组合,因为只有0和1的值,我们可以找到0和2的值(0 + 0和1 + 1)。
inds <- rowSums(expand.grid(v, v))
matrix(+(inds == 0 | inds == 2), nrow = length(v))
# [,1] [,2] [,3] [,4]
#[1,] 1 0 0 1
#[2,] 0 1 1 0
#[3,] 0 1 1 0
#[4,] 1 0 0 1
因为,对角线元素对你来说并不重要,我会保持原样,或者如果你想改变,你可以使用@gusus的答案中所示的diag
。
另一种(效率稍低)方法比使用outer
方法更为sapply
:
out <- sapply(v, function(x){
x == v
})
diag(out) <- 0L
out
[,1] [,2] [,3] [,4]
[1,] 0 0 0 1
[2,] 0 0 1 0
[3,] 0 1 0 0
[4,] 1 0 0 0
长度为1000的矢量上的微microbenchmark
:
> test <- microbenchmark("LAP" = sapply(v, function(x){
+ x == v
+ }),
+ "markus" = outer(v, v, `==`), times = 1000, unit = "ms")
> test
Unit: milliseconds
expr min lq mean median uq max neval
LAP 3.973111 4.065555 5.747905 4.573002 6.324607 101.03498 1000
markus 3.515725 3.535067 4.852606 3.694924 4.908930 84.85184 1000
如果你允许主对角线为1,那么无论v
有多大,在这个矩阵中总会有两个唯一的行v
和1 - v
。 由于矩阵是对称的,因此它也有两个这样的唯一列。 这使得构造该矩阵变得微不足道。
## example `v`
set.seed(0)
v <- sample.int(2, 10, replace = TRUE) - 1L
#[1] 1 0 0 1 1 0 1 1 1 1
## column expansion from unique columns
cbind(v, 1 - v, deparse.level = 0L)[, 2 - v]
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 1 0 0 1 1 0 1 1 1 1
# [2,] 0 1 1 0 0 1 0 0 0 0
# [3,] 0 1 1 0 0 1 0 0 0 0
# [4,] 1 0 0 1 1 0 1 1 1 1
# [5,] 1 0 0 1 1 0 1 1 1 1
# [6,] 0 1 1 0 0 1 0 0 0 0
# [7,] 1 0 0 1 1 0 1 1 1 1
# [8,] 1 0 0 1 1 0 1 1 1 1
# [9,] 1 0 0 1 1 0 1 1 1 1
#[10,] 1 0 0 1 1 0 1 1 1 1
这个矩阵的目的是什么?
如果有n0
零和n1
个,则矩阵将具有维度(n0 + n1) x (n0 + n1)
,但矩阵中只有(n0 x n0 + n1 x n1)
个。 因此对于长向量v
,矩阵是稀疏的。 实际上,它具有超级稀疏性,因为它具有大量重复的行/列。
显然,如果你想在这个矩阵中存储1的位置,你可以简单地得到它而不需要形成这个矩阵。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.