R/pkgnet.R

Defines functions pkgnet pkgnet.default pkgnet.character pkgnet.matrix

Documented in pkgnet pkgnet.character pkgnet.default pkgnet.matrix

#' Build a network based on package availability matrix
#' 
#' Given the matrix as returned by \code{available.packages} construct a graph,
#' of class \code{igraph} of inter-package relations.
#' 
#' The resulting graph (object of class \code{igraph}) is a multigraph: there
#' can be multiple relationships between any given pair of vertices. Different
#' types of relations can be disentagled using edge attribute called
#' \code{type}. It stores the type of relation as provided with \code{enams}
#' argument.
#' 
#' @param object a matrix as returned by \code{\link{available.packages}} or a 
#'   character scalar, one of \code{"cran"} or \code{"bioc"} to fetch and
#'   process packages available on CRAN or on Bioconductor, or an URL to a
#'   CRAN-like repository.
#' @param enams character, names of columns of \code{a} that are to be used as 
#'   edge attributes
#' @param vnams character, names of columns of \code{a} that are to be used as 
#'   vertex attributes
#' @param ap_args \code{NULL} or list of arguments passed to
#'   \code{\link{available.packages}}
#' @param ... arguments passed to/from other methods
#' 
#' @return Object of class \code{igraph}.
#' 
#' @seealso \code{\link{available.packages}}, \code{\link{graph.data.frame}}
#' 
#' @examples
#' \dontrun{
#' a <- available.packages(contrib.url("http://cran.r-project.org", "source"))
#' g <- pkgnet(a)
#' summary(g)
#' }
#' 
#' 
#' @export 
pkgnet <- function(object, ...) UseMethod("pkgnet")


#' @method pkgnet default
#' @rdname pkgnet
#' @export
pkgnet.default <- function(object, ...) {
  stop("don't know how to handle object of class ", oldClass(object))
}


#' @method pkgnet character
#' @rdname pkgnet
#' @export
pkgnet.character <- function(object, ap_args=NULL, ...) {
  u <- switch(object,
              cran = "https://cloud.r-project.org",
              bioc = "https://bioconductor.org/packages/3.0/bioc",
              object)
  a <- do.call("available.packages", c(list(repos=u), ap_args))
  pkgnet.matrix(a, ...)
}

#' @method pkgnet matrix
#' @rdname pkgnet
#' @export
pkgnet.matrix <- function(object, 
                   enams=c("Depends", "Suggests", "Imports", "Enhances", "LinkingTo"),
                   vnams=c("Version", "Priority", "License", "License_is_FOSS", 
                           "License_restricts_use", "OS_type", "Archs", "MD5sum", "NeedsCompilation",
                           "File", "Repository"),
                   ...
) {
  # check available relations
  i <- enams %in% colnames(object)
  if(!all(i)) 
    stop(paste("fields not found:", paste(enams[!i], collapse=", ")))
  # check other fields
  i <- vnams %in% colnames(object)
  if(!all(i)) 
    stop(paste("fields not found:", paste(vnams[!i], collapse=", ")))
  # list of edgelists and nodes lists
  l <- lapply(enams, function(vn)
  {
    # split on commas and drop newline
    alt <- strsplit( gsub("\n", "", object[,vn]), ", *")
    # get rid of package versions
    el <- lapply(alt, function(x)
    {
      rval <- gsub( "\\(.*\\)", "", x)
      stats::na.omit( gsub(" +", "", rval) )
    } )
    len <- sapply(el, length)
    # edge list
    edges <- data.frame( ego=rep(names(el), len), alter=unlist(el),
                         type=rep(vn, sum(len)), stringsAsFactors=FALSE)
    # node list
    nodes <- data.frame(name=sort(unique(c(names(el), unlist(el)))),
                        stringsAsFactors=FALSE)
    # add package attributes for 'object'
    mv <- match(nodes$name, object[,"Package"])
    z <- as.data.frame(object[mv, vnams], stringsAsFactors=FALSE)
    rownames(z) <- NULL
    nodes <- cbind( nodes, z )
    list(nodes=nodes, edges=edges)
  } )
  nodes <- do.call("rbind", lapply(l, "[[", "nodes"))
  nodes <- unique(nodes)
  edges <- do.call("rbind", lapply(l, "[[", "edges"))
  rval <- igraph::graph.data.frame(edges, vertices=nodes)
  rval
}
mbojan/cranet documentation built on May 14, 2019, 4:04 a.m.