Преобразовать двоичный вектор в двоичную матрицу - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть двоичный вектор, который содержит информацию о том, произошло ли какое-либо событие для какого-либо наблюдения:

v <- c(0,1,1,0)

Я хочу достичь матрицы, которая содержит информацию обо всех двумерных парах наблюдений в этомвектор.То есть, если два наблюдения имеют 0 или оба имеют 1 в этом векторе v, они должны получить 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 может быть значительного размера.

Спасибо!

Ответы [ 4 ]

0 голосов
/ 30 ноября 2018

Если вы разрешите основную диагональ равной 1, то в этой матрице всегда будут две уникальные строки v и 1 - v, независимо от того, насколько велика 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 в этой матрице, вы можете просто получить ее, не формируя эту матрицу ввсе.

0 голосов
/ 30 ноября 2018

Другой вариант с 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

Поскольку диагональный элемент для вас не важен, я сохраню его, как есть, или, если вы хотите изменить, вы можете использовать diag, как показано в ответе @ markus.

0 голосов
/ 30 ноября 2018

Другой (немного менее эффективный) подход, чем использование 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

microbenchmark для вектора длины 1000:

> 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
0 голосов
/ 30 ноября 2018

Мы можем использовать 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
...