USCCANA / netdiffuseR

netdiffuseR: Analysis of Diffusion and Contagion Processes on Networks
https://USCCANA.github.io/netdiffuseR
Other
85 stars 21 forks source link

Create a conversion from-to different network formats #7

Open gvegayon opened 7 years ago

gvegayon commented 7 years ago

What

There's already work on this going on (see graph_data.R#L44). Ideally, we need a function that generates a raw/generic graph format made of basic R structures (at most dgCMatrix objects).

Why

The idea is to use a generic class of graph throughout the package in the following form:

fun <- function(graph, ...) {
   fun(as_generic_graph(graph), ...)
}

fun.generic <- function(graph) {
  ...routine...
}

This way it will be easier to extend netdiffuseR to other packages/formats

Details

The generic class should be, of course, a generalization of a annotated networks with some special attributes. For now, I see:

  1. Dynamic graph object: a list of edgelists (that way multiple edges can be stored)
  2. Vertex attributes: A list of data frames.
  3. Vertex labels: A character vector with vertices names.
  4. Slices labels: A character vector with slices names
  5. Metadata:
    1. Directed: Logical scalar
    2. Valued: Logical scalar
    3. Autolinks: Logical scalar
    4. Name: Character scalar
    5. Description: Character scalar
    6. Original class: name of the class

Furthermore, this is more a list of possible outcomes, since it might be more efficient to, instead of fully generating a generic graph. It could be a function that reads/writes info depending on the graph class. For example:

net_readfuns <- function(graph) {
  gclass  <- class(graph)
  funname <- paste0("net_readfuns_", gclass[1])

  # Checking if there is methods
  if (!exists(funname, envir="netdiffuseR"))  
    stop("No functions defined for graph of class -", gclass,"-.")

  return(get(funname, envir = "netdiffuseR"))
} 

Or even better, a S3 class object with the following structure

The read/write functions can be specified as a lose object per class name, for example,

# Function to capture specs
readwrite_ <- function(graph) {
  gclass  <- class(graph)
  ans <- paste0("readwrite_", gclass[1])

  # Checking if there is methods
  if (!exists(ans, envir="netdiffuseR"))  
    stop("No functions defined for graph of class -", gclass,"-.")

  ans <- get(funname, envir = "netdiffuseR")
  ans$graph <- graph
  return(ans)
} 

# igraph specs
readwrite_igraph <- list(
  graph = NULL,
  gclass = "igraph",
  read = list(
    adjmat = function(x) {igraph::as_adjmat(x)},
    ...
  ),
  ...
)

Or perhaps, a more elegant way of doing this would be by crating a single graph_io object as follows:

graph_io <- list(igraph = new.env(), sna = new.env(), dgCMatrix = new.env(), matrix = new.env())

# Igraph class
graph_io$igraph <- list(graph = NULL, gclass = "igraph", read = ls(), write = ls())
graph_io$igraph$read <- list(
  adjmat = function() igraph::as_adj(graph),
  ...
)

# sna class
graph_io$igraph <- list(graph = NULL, gclass = "igraph", read = ls(), write = ls())
graph_io$igraph$read <- list(
  adjmat = function() igraph::as_adj(graph),
  ...
)