Лучший способ выделить матрицу в R, NULL vs NA?
Я пишу R-код для создания квадратной матрицы. Поэтому мой подход:
- Выделите матрицу нужного размера
- Прокрутите каждый элемент моей матрицы и заполните его соответствующим значением
Мой вопрос очень прост: каков наилучший способ предварительно выделить эту матрицу? До сих пор у меня есть два пути:
> x <- matrix(data=NA,nrow=3,ncol=3)
> x
[,1] [,2] [,3]
[1,] NA NA NA
[2,] NA NA NA
[3,] NA NA NA
или
> x <- list()
> length(x) <- 3^2
> dim(x) <- c(3,3)
> x
[,1] [,2] [,3]
[1,] NULL NULL NULL
[2,] NULL NULL NULL
[3,] NULL NULL NULL
Насколько я вижу, первый - более сжатый метод, чем последний. Кроме того, первая заполняет матрицу NA, тогда как последняя заполняется NULL.
Каков "лучший" способ сделать это? В этом случае я определяю "лучше" как "лучшую производительность", потому что это статистические вычисления, и эта операция будет выполняться с большими наборами данных.
В то время как первый более сжатый, это не удивительно легко понять, поэтому я чувствую, что это может пойти в любом случае.
Кроме того, в чем разница между NA и NULL в R?? NA и? NULL скажите мне, что "NA" имеет длину "1", тогда как NULL имеет длину "0" - но есть ли здесь больше? Или лучшая практика? Это повлияет на метод, который я использую для создания моей матрицы.
Ответы
Ответ 1
Если вы сомневаетесь, проверьте себя. Первый подход проще и быстрее.
> create.matrix <- function(size) {
+ x <- matrix()
+ length(x) <- size^2
+ dim(x) <- c(size,size)
+ x
+ }
>
> system.time(x <- matrix(data=NA,nrow=10000,ncol=10000))
user system elapsed
4.59 0.23 4.84
> system.time(y <- create.matrix(size=10000))
user system elapsed
0.59 0.97 15.81
> identical(x,y)
[1] TRUE
Относительно разницы между NA и NULL:
На самом деле существует четыре специальные константы.
Кроме того, существует четыре специальные константы: NULL, NA, Inf и NaN.
NULL используется для указания пустого объекта. NA используется для отсутствующих значений данных ( "Недоступно" ). Inf обозначает бесконечность, а NaN - не-число в исчислении с плавающей точкой IEEE (например, результаты операций соответственно 1/0 и 0/0).
Вы можете прочитать в руководство R по определению языка.
Ответ 2
В соответствии с этой статьей мы можем сделать лучше, чем предварительное распределение с помощью NA
путем предварительного распределения с помощью NA_real_
. Из статьи:
как только вы присвоите числовое значение любой из ячеек в "x", сначала нужно будет заставить матрицу зацикливаться на число, когда назначается новое значение. Исходно выделенная логическая матрица была распределена напрасно и просто добавляет ненужный объем памяти и дополнительную работу для сборщика мусора. Вместо этого выделите его, используя NA_real_ (или NA_integer_ для целых чисел)
Как рекомендуется: пусть протестировать его.
testfloat = function(mat){
n=nrow(mat)
for(i in 1:n){
mat[i,] = 1.2
}
}
>system.time(testfloat(matrix(data=NA,nrow=1e4,ncol=1e4)))
user system elapsed
3.08 0.24 3.32
> system.time(testfloat(matrix(data=NA_real_,nrow=1e4,ncol=1e4)))
user system elapsed
2.91 0.23 3.14
И для целых чисел:
testint = function(mat){
n=nrow(mat)
for(i in 1:n){
mat[i,] = 3
}
}
> system.time(testint(matrix(data=NA,nrow=1e4,ncol=1e4)))
user system elapsed
2.96 0.29 3.31
> system.time(testint(matrix(data=NA_integer_,nrow=1e4,ncol=1e4)))
user system elapsed
2.92 0.35 3.28
В моих тестовых случаях разница небольшая, но она там.
Ответ 3
rows<-3
cols<-3
x<-rep(NA, rows*cols)
x1 <- matrix(x,nrow=rows,ncol=cols)