Невозможно принудить класс матричных чисел к целому

Я пишу матрицу смежности в R так:

neighbours <- array(0, c(100,100))
for (i in 1:100) { neighbours[i,i] = 1 }    #reflexive

Но тогда я замечаю, что class(neighbours) - double matrix. Это займет слишком много места с большей матрицей. Поэтому я хочу принудить тип к integer или, что еще лучше, поскольку это ненаправлено, logical.

Но...

> class(neighbours[5])
[1] "numeric"
> class(neighbours[5]) <- "integer"
> class(neighbours[5])
[1] "numeric"

Не слушайте меня!

Ответ 1

Лучше не инициализировать его как числовое, но если вы не можете этого сделать, установите storage.mode:

R> neighbours <- array(0, c(100,100))
R> for (i in 1:100) { neighbours[i,i] = 1 }
R> str(neighbours)
 num [1:100, 1:100] 1 0 0 0 0 0 0 0 0 0 ...
R> storage.mode(neighbours) <- "integer"
R> str(neighbours)
 int [1:100, 1:100] 1 0 0 0 0 0 0 0 0 0 ...
R> storage.mode(neighbours) <- "logical"
R> str(neighbours)
 logi [1:100, 1:100] TRUE FALSE FALSE FALSE FALSE FALSE ...

Ответ 2

Возможно, мне что-то не хватает, но почему бы просто не объявить его как логический массив впереди?

neighbors <- array(FALSE, c(100,100))
diag(neighbors) <- TRUE

Сравнение двух:

> object.size(array(0, c(100,100)))
80200 bytes
> object.size(array(FALSE, c(100,100)))
40200 bytes

EDIT: Мне было бы интересно узнать, почему логический массив занимает 4B на запись, хотя...

Ответ 3

Для тех, кто все еще ищет метод, чтобы принудить существующую числовую матрицу к целочисленному:

m2 <- apply (m, c (1, 2), function (x) {
  (as.integer(x))
  })

С (1, 2) означает применение функции к строкам и столбцам. Затем тестирование класса элементов дает:

> class(m2[1,])
[1] "integer"
> class(m[1,])
[1] "numeric"
> 

Я искал что-то вроде этого, потому что мне нужно было преобразовать уже существующую численную матрицу. Это было результатом очень медленных вычислений, поэтому изменение кода потребовало бы гораздо больше времени, чем просто преобразование результата.

Ответ 4

Один из вариантов состоит в том, чтобы сначала заполнить целое число 0 (0L), а затем заменить диагональ целым числом 1, (1L)

m <- matrix(0L, 100, 100)
diag(m) <- 1L

Это половина размера более простого способа создания диагональной матрицы в R:

m2 <- diag(1L, 100, 100)

> object.size(m)
40200 bytes
> object.size(m2)
80200 bytes

Следовательно, выделение целочисленной матрицы m, тогда изменение диагонали приводит к самой компактной плотной матрице.

Ответ 5

В пакете Matrix (который теперь является стандартным пакетом) есть суперсетка sparseMatrix. Если вы хотите разреженную диагональную матрицу, вы можете создать ее с помощью

library(Matrix) 
Matrix(diag(1,4) , sparse=TRUE)
#---------
4 x 4 sparse Matrix of class "dsCMatrix"

[1,] 1 . . .
[2,] . 1 . .
[3,] . . 1 .
[4,] . . . 1

Дальнейшая мысль. Если вы хотите изменить режим матрицы на целое и не волнует, что он остается плотным:

> m <- matrix(rnorm(25), 5)
> m[] <- as.integer(m)  
# you do need those square-brackets or the structure becomes a dimensionless vector.
> m
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0   -1    0    0
[2,]    1    0    0    0    0
[3,]    1    0    0    0    0
[4,]    0    0    0    0    0
[5,]    0    0    0   -1    0

Еще одна мысль, спровоцированная замечанием Гэвина: если вы намерены представлять "смежность", и это действительно большое пространство для примера, вы можете просто использовать класс sparseMatrix в качестве модели и вместо этого использовать матрицу из двух столбцов с числа пар в столбцах. Это не совсем так, как разреженныеМатрисы содержат свою строку, столбец и значения, но для вашей проблемы может работать режим хранения в 2 столбца. См. Обработанные примеры в пакете "igraph". Я думаю, ваша проблема может быть представлена ​​как неориентированный граф.