Constructs a "repulsion graph" derived from an input graph `W` and a class structure graph `cg`. The resulting graph retains only the edges from `W` that connect nodes belonging to *different* classes according to `cg`. Edges connecting nodes within the same class are removed (or "repulsed").
Usage
repulsion_graph(
W,
cg,
method = c("weighted", "binary"),
threshold = 0,
norm_fac = 1
)Arguments
- W
An input graph object. Can be a `Matrix` object (e.g., `dgCMatrix`) representing the adjacency matrix, or a `neighbor_graph` object. Edge weights are used if `method="weighted"`.
- cg
A `class_graph` object defining the class membership of the nodes in `W`. Must have the same dimensions as `W`.
- method
`character`. Specifies how to handle the weights of the remaining (between-class) edges: - `"weighted"` (default): Retains the original weights from `W`. - `"binary"`: Sets the weight of all remaining edges to 1.
- threshold
`numeric`. A threshold applied to the input graph `W` *before* filtering by class. Edges in `W` with weights strictly below this value are discarded. Default is 0.
- norm_fac
`numeric`. A normalization factor applied *only* if `method = "weighted"`. The weights of the retained edges are divided by this factor. Default is 1 (no normalization).
Value
A `repulsion_graph` object (inheriting from `neighbor_graph`), representing the filtered graph containing only between-class edges.
Details
This function takes an existing graph `W` (representing similarities, connections, etc.) and filters it based on class labels. The `class_graph` object `cg` provides a binary adjacency matrix where `1` indicates nodes belong to the *same* class. By taking the complement (`!adjacency(cg)`), we get a mask where `1` indicates nodes belong to *different* classes. Element-wise multiplication (`W * !adjacency(cg)`) effectively removes within-class edges from `W`.
The `method` argument controls whether the remaining edge weights are kept as is (`"weighted"`) or converted to binary indicators (`"binary"`).
This type of graph is useful when focusing on interactions *between* distinct groups or classes within a larger network or dataset.
Examples
library(Matrix)
set.seed(123)
N <- 50
X <- matrix(rnorm(N * 5), N, 5)
W_adj <- Matrix(rsparsematrix(N, N, 0.1, symmetric = TRUE)) # Base adjacency
diag(W_adj) <- 0
W_ng <- neighbor_graph(W_adj) # Convert to neighbor_graph
labels <- factor(sample(1:3, N, replace = TRUE))
cg <- class_graph(labels)
R_weighted <- repulsion_graph(W_ng, cg, method = "weighted")
print(R_weighted)
#> Repulsion Graph Object
#> ----------------------
#> $G
#> IGRAPH 49bb281 U-W- 50 83 --
#> + attr: weight (e/n)
#> + edges from 49bb281:
#> [1] 1--20 1--26 1--28 1--37 1--48 2-- 4 2-- 9 2--24 2--47 3--10
#> [11] 3--13 3--20 3--45 4-- 6 4--14 4--35 4--37 4--44 4--48 4--50
#> [21] 5--34 5--45 6--12 6--23 6--24 6--28 6--30 6--38 8--23 8--40
#> [31] 8--50 9--18 9--38 10--15 10--22 10--30 11--21 11--30 11--37 11--38
#> [41] 13--36 13--40 14--16 14--20 14--50 15--18 15--28 15--39 15--48 16--36
#> [51] 17--18 17--30 17--33 17--39 17--47 17--50 18--19 20--22 21--33 23--43
#> [61] 24--30 24--37 24--43 24--48 24--50 25--46 26--41 26--45 27--47 28--30
#> [71] 28--49 31--35 32--33 32--37 35--48 36--49 37--40 37--44 41--50 43--47
#> + ... omitted several edges
#>
#> $params
#> $params$method
#> [1] "weighted"
#>
#> $params$threshold
#> [1] 0
#>
#> $params$norm_fac
#> [1] 1
#>
#> $params$original_W_type
#> [1] "neighbor_graph"
#>
#> $params$original_cg_levels
#> [1] "1" "2" "3"
#>
#>
#> attr(,"class")
#> [1] "repulsion_graph" "neighbor_graph"
#> Repulsion Params:
#> Method: weighted
#> Normalization Factor: 1
#> Input Threshold: 0
#> ----------------------
plot(R_weighted$G, vertex.color = labels, vertex.size=8, vertex.label=NA)
#> Warning: Non-positive edge weight found, ignoring all weights during graph layout.
title("Weighted Repulsion Graph (Edges only between classes)")
R_binary <- repulsion_graph(W_ng, cg, method = "binary")
print(R_binary)
#> Repulsion Graph Object
#> ----------------------
#> $G
#> IGRAPH 7352495 U-W- 50 83 --
#> + attr: weight (e/n)
#> + edges from 7352495:
#> [1] 1--20 1--26 1--28 1--37 1--48 2-- 4 2-- 9 2--24 2--47 3--10
#> [11] 3--13 3--20 3--45 4-- 6 4--14 4--35 4--37 4--44 4--48 4--50
#> [21] 5--34 5--45 6--12 6--23 6--24 6--28 6--30 6--38 8--23 8--40
#> [31] 8--50 9--18 9--38 10--15 10--22 10--30 11--21 11--30 11--37 11--38
#> [41] 13--36 13--40 14--16 14--20 14--50 15--18 15--28 15--39 15--48 16--36
#> [51] 17--18 17--30 17--33 17--39 17--47 17--50 18--19 20--22 21--33 23--43
#> [61] 24--30 24--37 24--43 24--48 24--50 25--46 26--41 26--45 27--47 28--30
#> [71] 28--49 31--35 32--33 32--37 35--48 36--49 37--40 37--44 41--50 43--47
#> + ... omitted several edges
#>
#> $params
#> $params$method
#> [1] "binary"
#>
#> $params$threshold
#> [1] 0
#>
#> $params$norm_fac
#> [1] NA
#>
#> $params$original_W_type
#> [1] "neighbor_graph"
#>
#> $params$original_cg_levels
#> [1] "1" "2" "3"
#>
#>
#> attr(,"class")
#> [1] "repulsion_graph" "neighbor_graph"
#> Repulsion Params:
#> Method: binary
#> Input Threshold: 0
#> ----------------------
data(iris)
X_iris <- as.matrix(iris[, 1:4])
labels_iris <- iris[, 5]
cg_iris <- class_graph(labels_iris)
W_iris_knn <- graph_weights(X_iris, k = 5, weight_mode = "heat", sigma = 0.7)
R_iris <- repulsion_graph(W_iris_knn, cg_iris, method = "weighted")
print(R_iris)
#> Repulsion Graph Object
#> ----------------------
#> $G
#> IGRAPH 22519ce U-W- 150 27 --
#> + attr: weight (e/n)
#> + edges from 22519ce:
#> [1] 57--128 60--107 64--139 67--107 69--120 71--128 71--139 71--150 73--120
#> [10] 73--124 73--134 73--147 78--111 78--148 84--102 84--114 84--120 84--124
#> [19] 84--127 84--134 84--135 84--143 84--147 84--150 85--107 90--107 91--107
#>
#> $params
#> $params$method
#> [1] "weighted"
#>
#> $params$threshold
#> [1] 0
#>
#> $params$norm_fac
#> [1] 1
#>
#> $params$original_W_type
#> [1] "neighbor_graph"
#>
#> $params$original_cg_levels
#> [1] "setosa" "versicolor" "virginica"
#>
#>
#> attr(,"class")
#> [1] "repulsion_graph" "neighbor_graph"
#> Repulsion Params:
#> Method: weighted
#> Normalization Factor: 1
#> Input Threshold: 0
#> ----------------------
plot(R_iris$G, vertex.color = as.numeric(labels_iris), vertex.size=5, vertex.label=NA)
title("Iris Repulsion Graph (k=5, heat weights)")