2014-01-16 3 views
3

Скажем, я хочу сохранить матрицу больших размеров в виде файла HDF5, а затем я хочу прочитать ТОЛЬКО некоторую нарезку матрицы по ID (по идентификатору я имею в виду строку имена матрицы, которые в моем случае уникальны, поэтому они могут служить идентификатором). Есть ли быстрый способ сделать это с использованием файлов HDF5?Файл hdf5 в R для быстрого произвольного доступа по ID

Пример.

my.mat = matrix(rnorm(400,2,1), nrow=100, ncol=4) 
rownames(my.mat) = paste("id", c(1:100), sep="") 

Тогда я сделаю что-то вроде этого:

h5createFile("test.h5") 
h5createDataset(file="test.h5", dataset="dat", dim=c(100,4), not sure what goes here) 

И тогда я хотел бы прочитать файл h5, но только кусочек построчно идентификатора, то есть только для чтения строк,

rows.to.read= c("id4", "id10", "id40") 

основная цель состоит в том, чтобы сделать разрезание чтение (нарезка чтение, я имею в виду чтение по идентификаторам) и написание целых hdf5 файлов как можно быстрее, так как они все очень большие наборы данных. Я бы предположил, что им нужно было бы хранить их таким образом, чтобы они хэшировались именем row_name, так что поиск по идентификатору может быстро развиваться без необходимости сортировки и/или сканирования всего документа.

ответ

0

Отметьте http://www.bioconductor.org/packages/devel/bioc/manuals/rhdf5/man/rhdf5.pdf страница 13, как читать в подмножествах, в частности аргумент index от h5read.

Это должно позволить вам читать в подмножествах.

Пакет не в CRAN, но первый ответ здесь: How to deal with hdf5 files in R? должен помочь вам добраться туда, где вам нужно, с точки зрения получения самого пакета.

+0

спасибо. Я считаю, что документация довольно критическая. INDEX: список индексов для подмножества. Длина списка должна соответствовать размерному расширению массива HDF5. Каждый элемент списка является целым вектором индексов. Элемент списка, равный NULL, выбивает все индексы в этом измерении. Подсчет R-стиля основан на 1. Как это перевести на индексирование всего имени строки? – Dnaiel

1

Я просто участвую в использовании пакета rhdf5. Похоже, для создания и индексации матрицы без dimnames, операции действительно прямо вперед

library(rhdf5) 
my.mat <- matrix(rnorm(400,2,1), nrow=100, ncol=4) 
fl <- tempfile() 
h5createFile(fl) 
h5write(my.mat, fl, "mat") 
h5read(fl, "mat", list(2:3, 3:4)) 
##   [,1]  [,2] 
## [1,] 0.3199968 1.947390 
## [2,] 1.3338179 2.623461 
h5read(fl, "mat", list(2:3, NULL)) 
##   [,1]  [,2]  [,3]  [,4] 
## [1,] 1.247648 -0.380762 0.3199968 1.947390 
## [2,] 3.157954 1.334057 1.3338179 2.623461 

Похоже, что пакет поддерживает некоторые функции, например, для написания data.frame объектов, но я в конечном итоге «My качению собственной 'для создания и подмножества/выбора для матрицы с dimnames. Вот функция записи, которая добавляет HDF5 атрибуты набора данных

h5matrix_write <- 
    function(obj, file, name, ...) 
{ 
    if (!is.matrix(obj) || is.null(dimnames(obj)) || 
     any(sapply(dimnames(obj), is.null))) 
     stop("'obj' must be a matrix with row and column names") 

    fid <- if (file.exists(file)) 
     H5Fopen(file) 
    else 
     H5Fcreate(file) 
    h5createDataset(fid, name, dim=dim(obj)) 
    did <- H5Dopen(fid, name) 

    h5createAttribute(fid, "rownames", nrow(obj), storage.mode="character", 
         size=max(nchar(rownames(obj)))) 
    h5createAttribute(fid, "colnames", ncol(obj), storage.mode="character", 
         size=max(nchar(colnames(obj)))) 

    h5writeDataset(obj, fid, name) 
    h5writeAttribute(rownames(obj), did, "rownames") 
    h5writeAttribute(colnames(obj), did, "colnames") 

    H5Dclose(did) 
    H5Fclose(fid) 

    file 
} 

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

h5matrix_select <- 
    function(file, name, i, j, ...) 
{ 
    ## FIXME: doesn't handle logical subsetting 
    fid <- H5Fopen(fl) 
    did <- H5Dopen(fid, "mat") 
    rownames <- H5Aread(H5Aopen(did, "rownames")) 
    if (missing(i)) 
     i <- seq_along(rownames) 
    else if (is.character(i)) { 
     i <- match(i, rownames) 
     if (any(is.na(i))) 
      stop(sum(is.na(i)), " unknown row names") 
    } 
    rownames <- rownames[i] 

    colnames <- H5Aread(H5Aopen(did, "colnames")) 
    if (missing(j)) 
     j <- seq_along(colnames) 
    else if (is.character(j)) { 
     j <- match(j, colnames) 
     if (any(is.na(j))) 
      stop(sum(is.na(j)), " unknown colnames") 
    } 
    colnames <- colnames[j] 

    value <- h5read(file, name, list(i, j)) 
    dimnames(value) <- list(rownames, colnames) 
    value 
} 

В действии:

dimnames(my.mat) <- list(paste0("rid", seq_len(nrow(my.mat))), 
         paste0("cid", seq_len(ncol(my.mat)))) 
fl <- h5matrix_write(my.mat, tempfile(), "mat") 
h5matrix_select(fl, "mat", 4:5, 2:3) 
##   cid2  cid3 
## rid4 0.4716097 2.3490782 
## rid5 2.0896238 0.5141749 
h5matrix_select(fl, "mat", 4:5) 
##   cid1  cid2  cid3  cid4 
## rid4 2.0947833 0.4716097 2.3490782 3.139687 
## rid5 0.8258651 2.0896238 0.5141749 2.509301 
set.seed(123) 
h5matrix_select(fl, "mat", sample(rownames(my.mat), 3), 2:3) 
##   cid2  cid3 
## rid29 0.6694079 3.795752 
## rid79 2.1635644 2.892343 
## rid41 3.7779177 1.685139 

(h5read(fl, "mat", read.attributes=TRUE) читает все в, я думаю, что простой подход от @jimmyb (сохранение имен строк в качестве отдельной переменной) также будет работать с rhdf5.

Уместно задавать вопросы о пакетах Bioconductor на Bioconductor mailing list, где автор пакета может с большей вероятностью увидеть его.

2

Вы можете попробовать пакет h5r, API которого немного легче, чем пакет rhdf5, но менее полнофункциональный.

require(h5r) 
my.mat = matrix(rnorm(400,2,1), nrow=100, ncol=4) 
rnames = paste("id", c(1:100), sep="") 

f = H5File("mymat.h5", 'w') 
d = createH5Dataset(f, "mymat", my.mat) 
r = createH5Dataset(f, "rnames", rnames) 

Тогда нарезка/индексирование целой/последовательности, как и ожидалось (и не все читали в память)

d[1:2,1:2] 
    [,1]  [,2] 
[1,] 2.777984 1.6040137 
[2,] 3.406609 -0.5168481 

На данный момент, вы должны прыгать через обруч с rownames, потому что hdf5 структуры данных все одного типа (без учета более сложных типов hdf5)

d[match(rows.to.read, r[]),] 

отказ от ответственности: я являюсь автором пакета h5r.

Смежные вопросы