Относительные вычислительные нагрузки матрицы и растра в R

Я был удивлен, обнаружив, что матрица, которую я создал из большого растра, якобы занимает в 35 000 раз больше памяти, чем родитель. Этот код демонстрирует:

> # comparison with R's built-in volcano data
> object.size(volcano)
42656 bytes
> object.size(as.matrix(volcano))
42656 bytes
> # comparison with my data
> class(region_utm)
[1] "RasterLayer"
attr(,"package")
[1] "raster"
> dim(region_utm)
[1] 7297 7297    1
> object.size(region_utm)
12128 bytes
> region_mat = as.matrix(region_utm)
> dim(region_mat)
[1] 7297 7297
> object.size(region_mat)
425969872 bytes

object.size(region_utm), безусловно, дает сильно заниженную оценку, поскольку 12 128 байтов недостаточно для содержания 53 млн значений, даже с учетом факторов, в частности, поскольку 87% (46 млн) являются уникальными значениями (согласно length(unique(region_utm))). Тогда не уверен, как получить реалистичную оценку памяти.

Однако построение растра выполняется значительно быстрее, чем работа с матрицей. Но я всегда думал, что матрицы примерно эквивалентны растрам без слотов пространственных данных, но я, должно быть, упустил важное различие между этими структурами данных. Благодарен за разъяснение того, что может объяснить это несоответствие памяти. Я довольно часто использую матричные рабочие процессы и должен понимать их ограничения.


Изменить: ожидается запрос на отчет str():

> str(region_mat)
 num [1:7297, 1:7297] NA NA NA NA NA NA NA NA NA NA ...
> summary(as.vector(region_mat))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
   -1.7    21.3   118.1   135.5   236.9  1020.0 1266438 
> str(region_utm)
Formal class 'RasterLayer' [package "raster"] with 12 slots
  ..@ file    :Formal class '.RasterFile' [package "raster"] with 13 slots
  .. .. ..@ name        : chr "/private/var/folders/kh/vlbqbp3n29lcvp491zbrnpl80000gn/T/R_raster_robinedwards/raster_tmp_2014-02-09_164243_1484_10601.grd"
  .. .. ..@ datanotation: chr "FLT8S"
  .. .. ..@ byteorder   : Named chr "little"
  .. .. .. ..- attr(*, "names")= chr "value"
  .. .. ..@ nodatavalue : num -1.7e+308
  .. .. ..@ NAchanged   : logi FALSE
  .. .. ..@ nbands      : int 1
  .. .. ..@ bandorder   : Named chr "BIL"
  .. .. .. ..- attr(*, "names")= chr "value"
  .. .. ..@ offset      : int 0
  .. .. ..@ toptobottom : logi TRUE
  .. .. ..@ blockrows   : int 0
  .. .. ..@ blockcols   : int 0
  .. .. ..@ driver      : chr "raster"
  .. .. ..@ open        : logi FALSE
  ..@ data    :Formal class '.SingleLayerData' [package "raster"] with 13 slots
  .. .. ..@ values    : logi(0) 
  .. .. ..@ offset    : num 0
  .. .. ..@ gain      : num 1
  .. .. ..@ inmemory  : logi FALSE
  .. .. ..@ fromdisk  : logi TRUE
  .. .. ..@ isfactor  : logi FALSE
  .. .. ..@ attributes: list()
  .. .. ..@ haveminmax: logi TRUE
  .. .. ..@ min       : num -1.73
  .. .. ..@ max       : num 1020
  .. .. ..@ band      : int 1
  .. .. ..@ unit      : chr ""
  .. .. ..@ names     : chr "layer"
  ..@ legend  :Formal class '.RasterLegend' [package "raster"] with 5 slots
  .. .. ..@ type      : chr(0) 
  .. .. ..@ values    : logi(0) 
  .. .. ..@ color     : logi(0) 
  .. .. ..@ names     : logi(0) 
  .. .. ..@ colortable: logi(0) 
  ..@ title   : chr(0) 
  ..@ extent  :Formal class 'Extent' [package "raster"] with 4 slots
  .. .. ..@ xmin: num 180386
  .. .. ..@ xmax: num 394918
  .. .. ..@ ymin: num 1879673
  .. .. ..@ ymax: num 2103691
  ..@ rotated : logi FALSE
  ..@ rotation:Formal class '.Rotation' [package "raster"] with 2 slots
  .. .. ..@ geotrans: num(0) 
  .. .. ..@ transfun:function ()  
  ..@ ncols   : int 7297
  ..@ nrows   : int 7297
  ..@ crs     :Formal class 'CRS' [package "sp"] with 1 slots
  .. .. ..@ projargs: chr "+proj=utm +zone=16 ellps=WGS84 +ellps=WGS84"
  ..@ history : list()
  ..@ z       : list()

person geotheory    schedule 10.02.2014    source источник
comment
Я не уверен, что у object.size есть метод S4. Кто-то с большим знанием (и интеллектом :-()), чем я могу знать наверняка.   -  person Carl Witthoft    schedule 10.02.2014
comment
Нет, это то, что объемные данные хранятся в файле по растру для этого объекта.   -  person mdsumner    schedule 10.02.2014


Ответы (1)


На самом деле, я почти уверен, что object.size не делает того, что вы хотите, с S4 объектами. Взгляните на код для cgwtools::lssize . Вот часть того, что я написал, с большой помощью других участников SO:

fb4 <- function(x) {
               if (isS4(x)) {
                      slots <- setNames(slotNames(x), slotNames(x))
                      lapply(lapply(slots, slot, object=x), fb4)
                      } else object.size(if(is.list(x)) unlist(x) else x)
                    }
            fb4(object)
            }
    sizes<-sapply(items,function(k) sum(unlist(s4gonebyte(get(k))) ),simplify=FALSE)

Это рекурсивное погружение в S4 слотов и подслотов.

person Carl Witthoft    schedule 10.02.2014
comment
Похоже, ты прав. Это также то, почему R не может сохранить растр с помощью save()? Жаль, что в документации нет очевидных деталей этого ограничения. - person geotheory; 11.02.2014
comment
@geotheory зависит от того, куда вы смотрите: попробуйте raster::stackSave и writeRaster среди других растровых инструментов в/из файла. - person Carl Witthoft; 11.02.2014
comment
Я знаю writeRaster, но он кажется менее эффективным для хранения или обратного чтения. Попробую stackSave - person geotheory; 11.02.2014