File: asNetwork.R

package info (click to toggle)
r-cran-intergraph 2.0-4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 392 kB
  • sloc: sh: 13; makefile: 2
file content (141 lines) | stat: -rw-r--r-- 4,706 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#' Convert objects to class "network"
#' 
#' Convert objects to class "network"
#' 
#' This is a generic function which dispatches on argument \code{x}.  It creates
#' objects of class "network" from other R objects.
#' 
#' The method for data frames is inspired by the similar function in package
#' \pkg{igraph}: \code{\link[igraph]{graph.data.frame}}.  It assumes that first
#' two columns of \code{x} constitute an edgelist.  The remaining columns are
#' interpreted as edge attributes. Optional argument \code{vertices} allows for
#' including vertex attributes.  The first column is assumed to vertex id, the
#' same that is used in the edge list. The remaining colums are interpreted as
#' vertex attributes.
#' 
#' The method for objects of class "igraph" takes the network of that class and
#' converts it to data frames using \code{\link{asDF}}. The network is recreated
#' in class "network" using \code{asNetwork.data.frame}. The function currently
#' does not support bipartite "igraph" networks.
#' 
#' @param x an R object to be coerced, see Details for the description of
#' available methods
#' @param amap data.frame with attribute copy/rename rules, see
#' \code{\link{attrmap}}
#' @param directed logical, whether the created network should be directed
#' @param vertices NULL or data frame, optional data frame containing vertex
#' attributes
#' @param \dots other arguments from/to other methods
#' @return Object of class "network".
#' @seealso \code{\link[igraph]{graph.data.frame}}
#' 
#' \code{\link{asIgraph}} for conversion in the other direction.
#'
#' @export
#'
#' @example examples/asNetwork.R
#'

asNetwork <- function(x, ...) UseMethod("asNetwork")

#' @method asNetwork data.frame
#' @export
#' @rdname asNetwork
asNetwork.data.frame <- function(x, directed=TRUE, vertices=NULL, ...)
{
  edb <- validateEL( as.data.frame(x) )
  # got vertex DB?
  if(!is.null(vertices))
  {
    vdb <- validateVDB( as.data.frame(vertices) )
    stopifnot(validNetDB(edb, vdb))
  }
  # number of vertices
  if(is.null(vertices)) nv <- length(unique(c(edb[,1], edb[,2])))
  else nv <- nrow(vertices)
  # create an empty network object
  rval <- network::network.initialize(nv, directed=directed, hyper=FALSE,
                                      multiple=any(duplicated(edb[,1:2])),
                                      loops=any(edb[,1] == edb[,2]))
  # add edges
  rval <- network::add.edges(rval, as.list(edb[,1]), as.list(edb[,2]))
  # add edge attribbutes
  if( ncol(edb) > 2)
    for(i in seq(3, ncol(edb)))
    {
      rval <- network::set.edge.attribute(rval, attrname=names(edb)[i], value=edb[,i])
    }
  # vertex attributes
  if( !is.null(vertices) && ncol(vertices) > 1 )
  {
    for( i in seq(2, ncol(vdb)) )
    {
      rval <- network::set.vertex.attribute(rval, attrname=names(vdb)[i],
                                            value=vdb[,i])
    }
  }
  rval
}


#' @method asNetwork igraph
#' @export
#' @rdname asNetwork
asNetwork.igraph <- function(x, amap=attrmap(), ...)
{
  object <- x
    na <- dumpAttr(object, "network")
    l <- asDF(object)

    ### prepare edge attributes
    eats <- attrmapmat("igraph", "network", "edge", db=amap)
    if( nrow(eats) > 0 )
    {
      # drop some
      todrop <- eats[ is.na(eats[,"toattr"]) , "fromattr" ]
      edges <- l$edges[ !( names(l$edges) %in% todrop ) ]
      # rename some
      names(edges) <- recode(names(edges), eats)
    } else
    {
      edges <-l$edges
    }

    ### prepare vertex attributes
    vats <- attrmapmat("igraph", "network", "vertex", db=amap)
    if( nrow(vats) > 0 )
    {
      # drop some
      todrop <- vats[ is.na(vats[,"toattr"]) , "fromattr" ]
      vertexes <- l$vertexes[ !( names(l$vertexes) %in% todrop )  ]
      # rename some
      names(vertexes) <- recode(names(vertexes), vats)
    } else
    {
      vertexes <- l$vertexes
    }

    ### make 'igraph' object
    rval <- asNetwork( edges,
        directed = igraph::is_directed(object),
        multiple = igraph::any_multiple(object),
        loops = igraph::any_loop(object),
        vertices = vertexes, ...)

    ### apply/rename/drop network attributes
    nats <- attrmapmat("igraph", "network", "network", db=amap)
    if( nrow(nats) > 0 )
    {
      todrop <- nats[ is.na(nats[,"toattr"]) , "fromattr" ]
      na <- na[ !( names(na) %in% todrop ) ]
      names(na) <- recode(names(na), nats)
    }
    if( length(na) > 0 )
    {
      for( naname in names(na) )
        network::set.network.attribute(rval, naname, na[[naname]])
    }
    if( is.function(network::get.network.attribute(rval, "layout")) )
      warning("network attribute 'layout' is a function, print the result might give errors")
    rval
}