#' readColMM
#'
#' Modified the `Matrix::readMM` function for reading matrices stored in the
#' Harwell-Boeing or MatrixMarket formats but only reads selected column.
#'
#' See \code{\link[Matrix]{readMM}}
#'
#' @param file the name of the file to be read from as a character scalar. Those
#' storing matrices in the MatrixMarket format usually end in ".mtx".
#' @param which.col An integer scalar, the column index
#' @param chunk, An integer scalar indicating the chunk size to use,
#' i.e., number of rows to read at any one time.
#' @author Ruqian Lyu
#' @export
#' @examples
#' demo_path <-paste0(system.file("extdata",package = "comapr"),"/")
#' readColMM(file = paste0(demo_path,"s1_chr1_vi.mtx"), which.col=2,chunk=2)
#' @return
#' A sparse matrix object that inherits from the "Matrix" class which the original
#' dimensions.To get the vector of the specified column, one need to subset
#' the matrix to select the column with the same index.
#'
readColMM <- function(file,which.col,chunk=1000L)
{
stopifnot(length(which.col)==1)
if (is.character(file))
file <- if(file == "") stdin() else file(file)
if (!inherits(file, "connection"))
stop("'file' must be a character string or connection")
if (!isOpen(file)) {
open(file)
on.exit(close(file))
}
scan1 <- function(what, ...)
scan(file, nmax = 1, what = what, quiet = TRUE, ...)
if (scan1(character()) != "%%MatrixMarket")# hdr
stop("file is not a MatrixMarket file")
if (!(typ <- tolower(scan1(character()))) %in% "matrix")
stop(gettextf("type '%s' not recognized", typ), domain = NA)
if (!(repr <- tolower(scan1(character()))) %in% c("coordinate", "array"))
stop(gettextf("representation '%s' not recognized", repr), domain = NA)
elt <- tolower(scan1(character()))
if (!elt %in% c("real", "complex", "integer", "pattern"))
stop(gettextf("element type '%s' not recognized", elt), domain = NA)
sym <- tolower(scan1(character()))
if (!sym %in% c("general", "symmetric", "skew-symmetric", "hermitian"))
stop(gettextf("symmetry form '%s' not recognized", sym), domain = NA)
nr <- scan1(integer(), comment.char = "%")
nc <- scan1(integer())
nz <- scan1(integer())
checkIJ <- function(els) {
if(any(els$i < 1 | els$i > nr))
stop("readMM(): row values 'i' are not in 1:nr", call.=FALSE)
if(any(els$j < 1 | els$j > nc))
stop("readMM(): column values 'j' are not in 1:nc", call.=FALSE)
}
if (repr == "coordinate") {
switch(elt,
"real" = ,
"integer" = {
## TODO: the "integer" element type should be returned as
## an object of an "iMatrix" subclass--once there are
pointer.col <- 0
while(pointer.col != which.col){
els <- scan1(what = list(i = integer(),
j = integer(),
x = numeric()))
pointer.col <- els$j
}
# Reading it in, chunk by chunk (see behavior of nmax= when what=
# is a list).
els <- list(i=els$i,j=els$j,x=els$x)
repeat {
current <- scan(file, what=list(i= integer(),
j= integer(),
x= numeric()),
nmax=chunk, quiet=TRUE)
checkIJ(current)
if ((current$j[length(current$j)] != which.col) |
(length(current$i) < chunk)){
els <- list(i = c(els$i,current$i[current$j==which.col]),
j = c(els$j,current$j[current$j==which.col]),
x = c(els$x,current$x[current$j==which.col]))
break
} else {
els <- list(i = c(els$i,current$i),
j = c(els$j,current$j),
x = c(els$x,current$x))
}
}
switch(sym,
"general" = {
new("dgTMatrix", Dim = c(nr, nc), i = els$i - 1L,
j = els$j - 1L, x = els$x)
},
"symmetric" = {
new("dsTMatrix", uplo = "L", Dim = c(nr, nc),
i = els$i - 1L, j = els$j - 1L, x = els$x)
},
"skew-symmetric" = {
stop("symmetry form 'skew-symmetric' not yet implemented
for reading")
## FIXME: use dgT... but must expand the (i,j,x) slots!
new("dgTMatrix", uplo = "L", Dim = c(nr, nc),
i = els$i - 1L, j = els$j - 1L, x = els$x)
},
"hermitian" = {
stop("symmetry form 'hermitian' not yet implemented for
reading")
},
## otherwise (not possible; just defensive programming):
stop(gettextf("symmetry form '%s' is not yet implemented",
sym), domain = NA)
)
},
"pattern" = {
els <- scan(file, nmax = nz, quiet = TRUE,
what = list(i = integer(), j = integer()))
checkIJ(els)
switch(sym,
"general" = {
new("ngTMatrix", Dim = c(nr, nc),
i = els$i - 1L, j = els$j - 1L)
},
"symmetric" = {
new("nsTMatrix", uplo = "L", Dim = c(nr, nc),
i = els$i - 1L, j = els$j - 1L)
},
"skew-symmetric" = {
stop("symmetry form 'skew-symmetric' not yet implemented
for reading")
## FIXME: use dgT... but must expand the (i,j,x) slots!
new("ngTMatrix", uplo = "L", Dim = c(nr, nc),
i = els$i - 1L, j = els$j - 1L)
},
"hermitian" = {
stop("symmetry form 'hermitian' not yet implemented for
reading")
},
## otherwise (not possible; just defensive programming):
stop(gettextf("symmetry form '%s' is not yet implemented",
sym), domain = NA)
)
},
"complex" = {
stop("element type 'complex' not yet implemented")
},
## otherwise (not possible currently):
stop(gettextf("'%s()' is not yet implemented for element type '%s'",
"readMM", elt), domain = NA))
}
else
stop(gettextf("'%s()' is not yet implemented for representation '%s'",
"readMM", repr), domain = NA)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.