Skip to content

Commit db764a7

Browse files
committed
function visualize
1 parent cf22d04 commit db764a7

4 files changed

Lines changed: 183 additions & 1 deletion

File tree

DESCRIPTION

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@ Encoding: UTF-8
3030
LazyData: true
3131
Imports:
3232
igraph,
33+
ggplot2,
34+
grDevices,
3335
Rcpp,
34-
Rdpack
36+
Rdpack,
37+
scales
3538
LinkingTo:
3639
Rcpp,
3740
RcppArmadillo

NAMESPACE

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@ export(gen_prec_sbm)
44
export(grasps)
55
export(sparsify_block_banded)
66
export(sparsify_block_diag)
7+
export(visualize)
8+
import(ggplot2)
79
importFrom(Rcpp,evalCpp)
810
importFrom(Rdpack,reprompt)
11+
importFrom(grDevices,colorRampPalette)
912
importFrom(igraph,as_adjacency_matrix)
1013
importFrom(igraph,sample_sbm)
14+
importFrom(scales,rescale)
1115
importFrom(stats,cov)
1216
useDynLib(grasps, .registration = TRUE)

R/visualize.R

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#' Visualize a Matrix with Group Boundaries
2+
#'
3+
#' @description
4+
#' Visualize a matrix (e.g., a precision, covariance, or adjacency matrix) as a
5+
#' heatmap with optional group-based reordering and dashed boundary lines
6+
#' separating group blocks.
7+
#'
8+
#' @param mat A p-by-p matrix.
9+
#'
10+
#' @param membership An integer vector specifying the group membership.
11+
#' The length of \code{membership} must be consistent with the dimension p.
12+
#'
13+
#' @param reorder_by_group A boolean (default = \code{FALSE}) specifying whether
14+
#' to reorder both rows and columns of \code{mat} according to \code{membership},
15+
#' such that variables from the same group are contiguous.
16+
#'
17+
#' @param colors A vector of colors specifying an n-color gradient scale for
18+
#' the fill aesthetics.
19+
#'
20+
#' @import ggplot2
21+
#' @importFrom grDevices colorRampPalette
22+
#' @importFrom scales rescale
23+
#'
24+
#' @return
25+
#' A \code{ggplot2} heatmap showing the matrix entries. Dashed lines indicate
26+
#' group boundaries. The plot title also reports matrix dimension and sparsity.
27+
#'
28+
#' @examples
29+
#' ## reproducibility for everything
30+
#' set.seed(1234)
31+
#'
32+
#' ## user-defined sampler
33+
#' my_gamma <- function(n) {
34+
#' rgamma(n, shape = 20, scale = 5)
35+
#' }
36+
#'
37+
#' ## block-structured precision matrix based on SBM
38+
#' sim <- gen_prec_sbm(p = 100, K = 5,
39+
#' within.prob = 0.5, between.prob = 0.05,
40+
#' weight.dists = list(my_gamma, "unif"),
41+
#' weight.paras = list(NULL, c(min = 0, max = 1)),
42+
#' min.eig = 0.1)
43+
#'
44+
#' ## visualization
45+
#' visualize(sim$Omega, sim$membership)
46+
#'
47+
#' @export
48+
49+
visualize <- function(mat, membership, reorder_by_group = FALSE,
50+
colors = colorRampPalette(
51+
c("#00007F", "blue", "#007FFF", "cyan", "#7FFF7F",
52+
"yellow", "#FF7F00", "red", "#7F0000"))(256)) {
53+
54+
p <- ncol(mat)
55+
if (length(membership) != p) {
56+
stop(sprintf("Length of 'membership' (%d) must equal the matrix dimension p (%d).",
57+
length(membership), p))
58+
}
59+
60+
## optionally reorder rows/cols by group membership
61+
if (reorder_by_group) {
62+
o <- order(membership)
63+
mat <- mat[o, o]
64+
membership <- membership[o]
65+
}
66+
67+
## compute group sizes and boundary positions for dashed lines
68+
grp_sizes <- table(membership)
69+
cuts <- cumsum(grp_sizes)
70+
bnds <- cuts[-length(cuts)] + 0.5 ## boundaries between groups
71+
y_bnds <- p - bnds + 1 ## flipped y, note: scale_y_discrete(limits = rev)
72+
73+
## declare
74+
Col <- Row <- value <- NULL
75+
76+
## plot data
77+
labs <- paste0("V", seq_len(p))
78+
plotData <- data.frame(
79+
Row = factor(rep(labs, times = p), levels = labs),
80+
Col = factor(rep(labs, each = p), levels = labs),
81+
value = as.vector(mat),
82+
check.names = FALSE
83+
)
84+
# plotData <- as.data.frame(mat) %>%
85+
# mutate(Row = factor(paste0("V", rownames(.)),
86+
# levels = paste0("V", rownames(.)))) %>%
87+
# pivot_longer(-Row, names_to = "Col", values_to = "value") %>%
88+
# mutate(Col = factor(Col, levels = levels(Row)))
89+
90+
## sparsity (proportion of zero entries)
91+
sparsity <- round(sum(mat == 0) / length(mat), 4)
92+
93+
## zero -> NA for better white rendering
94+
plotData$value[plotData$value == 0] <- NA
95+
96+
## color scaling range
97+
vmin <- min(plotData$value, na.rm = TRUE)
98+
vmax <- max(plotData$value, na.rm = TRUE)
99+
100+
ggplot(plotData, aes(x = Col, y = Row, fill = value)) +
101+
coord_fixed() +
102+
geom_tile() +
103+
guides(fill = guide_colourbar(title = NULL, barwidth = 0.5, barheight = 5)) +
104+
scale_y_discrete(limits = rev) +
105+
scale_fill_gradientn(colours = colors,
106+
values = rescale(c(vmin, 0, vmax)),
107+
limits = c(vmin, vmax),
108+
na.value = "white") +
109+
geom_vline(xintercept = bnds, linetype = "dashed") +
110+
geom_hline(yintercept = y_bnds, linetype = "dashed") +
111+
labs(x = NULL, y = NULL,
112+
title = sprintf("p = %d, Sparsity = %s", ncol(mat), sparsity)) +
113+
theme_bw() +
114+
theme(axis.text = element_blank(),
115+
axis.ticks = element_blank(),
116+
legend.ticks = element_blank(),
117+
# plot.margin = margin(1, 1, 1, 1, "mm"),
118+
plot.title = element_text(hjust = .5))
119+
}

man/visualize.Rd

Lines changed: 56 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)