File: py_objects.R

package info (click to toggle)
r-cran-leiden 0.3.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 508 kB
  • sloc: sh: 20; makefile: 2
file content (129 lines) | stat: -rw-r--r-- 4,464 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
##' convert to python object
##' @param object an igraph object or matrix
##' @param weights Parameters to pass to the Python leidenalg function (defaults initial_membership=None, weights=None). Weights are derived from weighted igraph objects and non-zero integer values of adjacency matrices.
##' @noRd
##' @description internal function to compute partitions by calling Python with reticulate
##' @keywords internal
make_py_object <- function(object, weights = NULL) {
  UseMethod("make_py_object", object)
}

make_py_object.matrix <- function(object, weights = NULL){
  #import python modules with reticulate
  numpy <- reticulate::import("numpy", delay_load = TRUE)
  leidenalg <- import("leidenalg", delay_load = TRUE)
  ig <- import("igraph", delay_load = TRUE)

  #convert matrix input (corrects for sparse matrix input)
  if(is.matrix(object) || is(object, "dgCMatrix")){
    object <- object
  } else{
    object <- as.matrix(object)
  }

  #compute weights if non-binary adjacency matrix given
  is_pure_adj <- all(as.logical(unlist(object)) == object)
  if (is.null(weights) && !is_pure_adj) {
    if(!is.matrix(object)) object <- as.matrix(object)
    #assign weights to edges (without dependancy on igraph)
    t_mat <- t(object)
    weights <- t_mat[t_mat!=0]
    #remove zeroes from rows of matrix and return vector of length edges
  }

  ##convert to python numpy.ndarray, then a list
  adj_mat_py <- r_to_py(object, convert = TRUE)
  if(is(object, "dgCMatrix")){
    adj_mat_py <- adj_mat_py$toarray()
  }
  adj_mat_py <- adj_mat_py$tolist()

  adj_mat_py
}

make_py_object.Matrix <- make_py_object.matrix

make_py_object.igraph <- function(object, weights = NULL){
  #import python modules with reticulate
  numpy <- import("numpy", delay_load = TRUE)
  leidenalg <- import("leidenalg", delay_load = TRUE)
  ig <- import("igraph", delay_load = TRUE)

  ##convert to python numpy.ndarray, then a list
  if(!is_named(object)){
    vertices <- as.list(as.character(V(object)))
  } else {
    vertices <- as.list(names(V(object)))
  }

  edges <- as_edgelist(object)
  dim(edges)
  edgelist <- list(rep(NA, nrow(edges)))
  for(ii in 1:nrow(edges)){
    edgelist[[ii]] <- as.character(edges[ii,])
  }

  py_graph <- ig$Graph()
  py_graph$add_vertices(r_to_py(vertices))
  py_graph$add_edges(r_to_py(edgelist))

  #compute weights if weighted graph given
  if(is_weighted(object)){
    #assign weights to edges (without dependancy on igraph)
    weights <- r_to_py(edge_attr(object)$weight)
    py_graph$es$set_attribute_values('weight', weights)
  }
  py_graph
}

make_py_object.data.frame <- function(object, weights = NULL){
  pd <- reticulate::import("pandas", delay_load = TRUE)
  adj_df_py <- pd$DataFrame(data = r_to_py(object, convert = TRUE))

  adj_df_py
}

##' convert to python igraph object
##' @param object an igraph object or matrix
##' @param weights Parameters to pass to the Python leidenalg function (defaults initial_membership=None, weights=None). Weights are derived from weighted igraph objects and non-zero integer values of adjacency matrices.
##' @noRd
##' @description internal function to compute partitions by calling Python with reticulate
##' @keywords internal
make_py_graph <- function(object, weights = NULL) {
  UseMethod("make_py_graph", object)
}

make_py_graph.matrix <- function(object, weights = NULL){
  #compute weights if non-binary adjacency matrix given
  is_pure_adj <- all(as.logical(unlist(object)) == object)
  if (is.null(weights) && !is_pure_adj) {
    if(!is.matrix(object)) object <- as.matrix(object)
    #assign weights to edges (without dependancy on igraph)
    t_mat <- t(object)
    weights <- t_mat[t_mat!=0]
    #remove zeroes from rows of matrix and return vector of length edges
  }

  #import python modules with reticulate
  numpy <- reticulate::import("numpy", delay_load = TRUE)
  leidenalg <- import("leidenalg", delay_load = TRUE)
  ig <- import("igraph", delay_load = TRUE)

  adj_mat_py <- make_py_object(object, weights = weights)

  #convert graph structure to a Python compatible object
  GraphClass <- if (!is.null(weights) && !is_pure_adj){
    ig$Graph$Weighted_Adjacency
  } else {
    ig$Graph$Adjacency
  }
  py_graph <- GraphClass(adj_mat_py)
}

make_py_graph.Matrix <- make_py_graph.matrix

make_py_graph.igraph <- make_py_object.igraph

make_py_graph.data.frame <- function(object, weights = NULL){
  py_graph <- make_py_graph(as.matrix(object), weights = weights)
}