Лучший способ выделить матрицу в R, NULL против NA? - PullRequest
33 голосов
/ 17 ноября 2009

Я пишу код R для создания квадратной матрицы. Итак, мой подход:

  1. Выделите матрицу правильного размера
  2. Перебрать каждый элемент моей матрицы и заполнить его соответствующим значением

Мой вопрос действительно прост: каков наилучший способ предварительно выделить эту матрицу? Пока у меня есть два пути:

> 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», но есть ли еще здесь Или лучшая практика? Это повлияет на то, какой метод я использую для создания своей матрицы.

Ответы [ 3 ]

46 голосов
/ 17 ноября 2009

Если сомневаешься, проверь себя. Первый подход проще и быстрее.

> 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 по определению языка .

4 голосов
/ 04 ноября 2014

Согласно этой статье мы можем добиться большего успеха, чем предварительное выделение с помощью 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 

Разница небольшая в моих тестовых случаях, но она есть.

0 голосов
/ 13 апреля 2017
rows<-3
cols<-3    
x<-rep(NA, rows*cols)
x1 <- matrix(x,nrow=rows,ncol=cols)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...