Skip to content

Commit 025566f

Browse files
committed
visualize() --> plot.grasps()
1 parent aac1829 commit 025566f

12 files changed

Lines changed: 135 additions & 138 deletions

NAMESPACE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Generated by roxygen2: do not edit by hand
22

3+
S3method(plot,grasps)
34
export(gen_prec_sbm)
45
export(grasps)
56
export(sparsify_block_banded)
6-
export(visualize)
77
import(ggplot2)
88
importFrom(Rcpp,evalCpp)
99
importFrom(Rdpack,reprompt)

R/gen_prec_sbm.R

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
#' @importFrom igraph as_adjacency_matrix sample_sbm
120120
#'
121121
#' @return
122-
#' A list with the following components:
122+
#' An object with S3 class "grasps" containing the following components:
123123
#' \describe{
124124
#' \item{Omega}{The precision matrix with SBM block structure.}
125125
#' \item{Sigma}{The covariance matrix, i.e., the inverse of \code{Omega}.}
@@ -141,6 +141,7 @@
141141
#' weight.dists = list(my_gamma, "unif"),
142142
#' weight.paras = list(NULL, c(min = 0, max = 5)),
143143
#' cond.target = 100)
144+
#' plot(sim)
144145
#'
145146
#' @export
146147

@@ -238,7 +239,9 @@ gen_prec_sbm <- function(d,
238239
## covariance matrix
239240
Sigma <- solve(Omega)
240241

241-
return(list(Omega = Omega, Sigma = Sigma,
242-
sparsity = sum(Omega == 0) / length(Omega),
243-
membership = membership))
242+
result <- list(Omega = Omega, Sigma = Sigma,
243+
sparsity = sum(Omega == 0) / length(Omega),
244+
membership = membership)
245+
class(result) <- "grasps"
246+
return(result)
244247
}

R/grasps.R

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@
115115
#' @importFrom Rdpack reprompt
116116
#'
117117
#' @return
118-
#' A list containing the following components:
118+
#' An object with S3 class "grasps" containing the following components:
119119
#' \describe{
120120
#' \item{hatOmega}{The estimated precision matrix.}
121121
#' \item{lambda}{The optimal regularization parameter.}
@@ -137,11 +137,26 @@
137137
#' \item{IC.score}{The information criterion score for each parameter
138138
#' combination when \code{crit} is set to \code{"AIC"}, \code{"BIC"},
139139
#' \code{"EBIC"}, or \code{"HBIC"}.}
140+
#' \item{membership}{The group membership.}
140141
#' }
141142
#'
142143
#' @references
143144
#' \insertAllCited{}
144145
#'
146+
#' @examples
147+
#' ## reproducibility for everything
148+
#' set.seed(1234)
149+
#'
150+
#' ## n-by-d data matrix
151+
#' X <- matrix(rnorm(200), 10, 20)
152+
#'
153+
#' ## group membership
154+
#' membership <- c(rep(1,5), rep(2,5), rep(3,4), rep(4,6))
155+
#'
156+
#' ## lasso, BIC
157+
#' res <- grasps(X = X, membership = membership, penalty = "lasso", crit = "BIC")
158+
#' plot(res)
159+
#'
145160
#' @export
146161

147162
grasps <- function(X, n = nrow(X), membership, penalty,
@@ -156,34 +171,37 @@ grasps <- function(X, n = nrow(X), membership, penalty,
156171
d <- ncol(X)
157172

158173
if (length(membership) != d) {
159-
stop("The length of 'membership' must equal the column dimension of X!")
174+
stop('The length of `membership` must equal the column dimension of `X`!')
160175
}
161176
if (!penalty %in% c("lasso", "adapt", "mcp", "scad")) {
162-
stop("Error in penalty! Available options: 'lasso', 'adapt', 'mcp', 'scad'.")
177+
stop('Error in `penalty`!\nAvailable options: "lasso", "adapt", "mcp", "scad".')
178+
}
179+
if (!crit %in% c("AIC", "BIC", "EBIC", "HBIC", "CV")) {
180+
stop('Error in `crit`!\nAvailable options: "AIC", "BIC", "EBIC", "HBIC", "CV".')
163181
}
164182
if (!all(lambda > 0)) {
165-
stop("The parameter 'lambda' must be positive!")
183+
stop('The parameter `lambda` must be positive!')
166184
}
167185
if (!all(alpha >= 0 & alpha <= 1)) {
168-
stop("The parameter 'alpha' must be in [0,1]!")
186+
stop('The parameter `alpha` must be in [0,1]!')
169187
}
170188
if (rho <= 0) {
171-
stop("The parameter 'rho' must be positive!")
189+
stop('The parameter `rho` must be positive!')
172190
}
173191
if (tau.incr <= 1) {
174-
stop("The parameter 'tau.incr' must be greater than 1!");
192+
stop('The parameter `tau.incr` must be greater than 1!')
175193
}
176194
if (tau.decr <= 1) {
177-
stop("The parameter 'tau.decr' must be greater than 1!");
195+
stop('The parameter `tau.decr` must be greater than 1!')
178196
}
179197
if (nu <= 1) {
180-
stop("The parameter 'nu' must be greater than 1!");
198+
stop('The parameter `nu` must be greater than 1!')
181199
}
182200
if (tol.abs <= 0) {
183-
stop("The parameter 'tol.abs' must be positive!");
201+
stop('The parameter `tol.abs` must be positive!')
184202
}
185203
if (tol.rel <= 0) {
186-
stop("The parameter 'tol.rel' must be positive!");
204+
stop('The parameter `tol.rel` must be positive!')
187205
}
188206

189207
if (isSymmetric(X)) {
@@ -262,11 +280,11 @@ grasps <- function(X, n = nrow(X), membership, penalty,
262280
if (crit == "CV") {
263281

264282
if(is.null(X)) {
265-
stop("CV requires the n-by-p data matrix!")
283+
stop('CV requires the n-by-d data matrix!')
266284
}
267285

268286
if (kfold < 2 | kfold > n) {
269-
stop("'kfold' must be between 2 and the row dimension of X!")
287+
stop('`kfold` must be between 2 and the row dimension of `X`!')
270288
}
271289

272290
CV <- ADMMsggm_CV(X = X, group_idx = group.idx, penalty = penalty,
@@ -323,6 +341,8 @@ grasps <- function(X, n = nrow(X), membership, penalty,
323341

324342
}
325343

344+
result$membership <- membership
345+
class(result) <- "grasps"
326346
return(result)
327347

328348
}

R/visualize.R renamed to R/plot.grasps.R

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,10 @@
1-
#' Visualize a Matrix with Group Boundaries
1+
#' Plot Function for "grasps" (Visualize a Matrix with Group Boundaries)
22
#'
33
#' @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
4+
#' Visualize a precision matrix as a heatmap with dashed boundary lines
65
#' separating group blocks.
76
#'
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.
7+
#' @param x An object with S3 class "grasps".
168
#'
179
#' @param colors A vector of colors specifying an n-color gradient scale for
1810
#' the fill aesthetics.
@@ -35,49 +27,47 @@
3527
#' }
3628
#'
3729
#' ## block-structured precision matrix based on SBM
38-
#' sim <- gen_prec_sbm(p = 100, K = 5,
30+
#' sim <- gen_prec_sbm(d = 100, K = 5,
3931
#' within.prob = 0.5, between.prob = 0.05,
4032
#' weight.dists = list(my_gamma, "unif"),
4133
#' weight.paras = list(NULL, c(min = 0, max = 1)),
42-
#' min.eig = 0.1)
34+
#' cond.target = 100)
4335
#'
4436
#' ## visualization
45-
#' visualize(sim$Omega, sim$membership)
37+
#' plot(sim)
4638
#'
4739
#' @export
40+
#' @noRd
4841

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)) {
42+
plot.grasps <- function(x, colors = NULL, ...) {
5343

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))
44+
if(is.null(x$hatOmega)) {
45+
mat <- x$Omega
46+
} else {
47+
mat <- x$hatOmega
5848
}
5949

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]
50+
d <- ncol(mat)
51+
if (is.null(colors)) {
52+
colors <- colorRampPalette(
53+
c("#00007F", "blue", "#007FFF", "cyan", "#7FFF7F",
54+
"yellow", "#FF7F00", "red", "#7F0000"))(256)
6555
}
6656

6757
## compute group sizes and boundary positions for dashed lines
68-
grp_sizes <- table(membership)
58+
grp_sizes <- table(x$membership)
6959
cuts <- cumsum(grp_sizes)
7060
bnds <- cuts[-length(cuts)] + 0.5 ## boundaries between groups
71-
y_bnds <- p - bnds + 1 ## flipped y, note: scale_y_discrete(limits = rev)
61+
y_bnds <- d - bnds + 1 ## flipped y, note: scale_y_discrete(limits = rev)
7262

7363
## declare
7464
Col <- Row <- value <- NULL
7565

7666
## plot data
77-
labs <- paste0("V", seq_len(p))
67+
labs <- paste0("V", seq_len(d))
7868
plotData <- data.frame(
79-
Row = factor(rep(labs, times = p), levels = labs),
80-
Col = factor(rep(labs, each = p), levels = labs),
69+
Row = factor(rep(labs, times = d), levels = labs),
70+
Col = factor(rep(labs, each = d), levels = labs),
8171
value = as.vector(mat),
8272
check.names = FALSE
8373
)
@@ -87,9 +77,6 @@ visualize <- function(mat, membership, reorder_by_group = FALSE,
8777
# pivot_longer(-Row, names_to = "Col", values_to = "value") %>%
8878
# mutate(Col = factor(Col, levels = levels(Row)))
8979

90-
## sparsity (proportion of zero entries)
91-
sparsity <- round(sum(mat == 0) / length(mat), 4)
92-
9380
## zero -> NA for better white rendering
9481
plotData$value[plotData$value == 0] <- NA
9582

@@ -101,15 +88,17 @@ visualize <- function(mat, membership, reorder_by_group = FALSE,
10188
coord_fixed() +
10289
geom_tile() +
10390
guides(fill = guide_colourbar(title = NULL, barwidth = 0.5, barheight = 5)) +
104-
scale_y_discrete(limits = rev) +
91+
scale_x_discrete(limits = labs, expand = c(0, 0)) +
92+
scale_y_discrete(limits = rev(labs), expand = c(0, 0)) +
10593
scale_fill_gradientn(colours = colors,
10694
values = rescale(c(vmin, 0, vmax)),
10795
limits = c(vmin, vmax),
10896
na.value = "white") +
10997
geom_vline(xintercept = bnds, linetype = "dashed") +
11098
geom_hline(yintercept = y_bnds, linetype = "dashed") +
11199
labs(x = NULL, y = NULL,
112-
title = sprintf("p = %d, Sparsity = %s", ncol(mat), sparsity)) +
100+
title = sprintf("Dimension = %d, Sparsity = %s", d,
101+
round(sum(mat == 0) / length(mat), 4))) +
113102
theme_bw() +
114103
theme(axis.text = element_blank(),
115104
axis.ticks = element_blank(),

R/sparsify_block_banded.R

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#' where groups whose labels differ by at most \code{neighbor.range} are
1515
#' considered neighbors and kept in the mask.
1616
#'
17-
#' @return A list containing:
17+
#' @return An object with S3 class "grasps" containing the following components:
1818
#' \describe{
1919
#' \item{Omega}{The masked precision matrix.}
2020
#' \item{Sigma}{The covariance matrix, i.e., the inverse of \code{Omega}.}
@@ -33,18 +33,15 @@
3333
#'
3434
#' ## default: keep blocks within ±1 of each group
3535
#' res1 <- sparsify_block_banded(est$hatOmega, membership, neighbor.range = 1)
36-
#' ## visualization
37-
#' visualize(res1$Omega, res1$membership)
36+
#' plot(res1)
3837
#'
3938
#' ## wider band: keep blocks within ±2 of each group
4039
#' res2 <- sparsify_block_banded(est$hatOmega, membership, neighbor.range = 2)
41-
#' ## visualization
42-
#' visualize(res2$Omega, res2$membership)
40+
#' plot(res2)
4341
#'
4442
#' ## special case: block-diagonal matrix
4543
#' res3 <- sparsify_block_banded(est$hatOmega, membership, neighbor.range = 0)
46-
#' ## visualization
47-
#' visualize(res3$Omega, res3$membership)
44+
#' plot(res3)
4845
#'
4946
#' @export
5047

@@ -64,7 +61,9 @@ sparsify_block_banded <- function(mat, membership, neighbor.range = 1) {
6461
## compute covariance
6562
Sigma <- solve(Omega)
6663

67-
return(list(Omega = Omega, Sigma = Sigma,
68-
sparsity = sum(Omega == 0) / length(Omega),
69-
membership = membership))
64+
result <- list(Omega = Omega, Sigma = Sigma,
65+
sparsity = sum(Omega == 0) / length(Omega),
66+
membership = membership)
67+
class(result) <- "grasps"
68+
return(result)
7069
}

README.Rmd

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,26 @@ devtools::install_github("Carol-seven/grasps")
6868
## Example
6969

7070

71-
```
71+
```{r}
7272
library(grasps)
7373
74+
## reproducibility for everything
7475
set.seed(1234)
7576
76-
X <- matrix(rnorm(200), 10, 20)
77-
membership <- c(rep(1,5), rep(2,5), rep(3,4), rep(4,6))
77+
## block-structured precision matrix based on SBM
78+
sim <- gen_prec_sbm(d = 100, K = 5,
79+
within.prob = 0.5, between.prob = 0.05,
80+
weight.dists = list("gamma", "unif"),
81+
weight.paras = list(c(shape = 20, scale = 5), c(min = 0, max = 1)),
82+
cond.target = 100)
83+
84+
## synthetic data
85+
library(MASS)
86+
X <- MASS::mvrnorm(n = 50, mu = rep(0, ncol(sim$Sigma)), Sigma = sim$Sigma)
7887
79-
res <- grasps(X, membership = membership, penalty = "lasso", crit = "BIC")
88+
## solution
89+
res <- grasps(X = X, membership = sim$membership, penalty = "lasso", crit = "BIC")
90+
plot(res)
8091
```
8192

8293

README.md

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,29 @@ You can install the development version of **grasps** from
4040

4141
## Example
4242

43-
library(grasps)
43+
``` r
44+
library(grasps)
4445

45-
X <- matrix(rnorm(200), 10, 20)
46-
membership <- c(rep(1,5), rep(2,5), rep(3,4), rep(4,6))
46+
## reproducibility for everything
47+
set.seed(1234)
4748

48-
res <- grasps(X, membership = membership, penalty = "lasso", crit = "BIC")
49+
## block-structured precision matrix based on SBM
50+
sim <- gen_prec_sbm(d = 100, K = 5,
51+
within.prob = 0.5, between.prob = 0.05,
52+
weight.dists = list("gamma", "unif"),
53+
weight.paras = list(c(shape = 20, scale = 5), c(min = 0, max = 1)),
54+
cond.target = 100)
55+
56+
## synthetic data
57+
library(MASS)
58+
X <- MASS::mvrnorm(n = 50, mu = rep(0, ncol(sim$Sigma)), Sigma = sim$Sigma)
59+
60+
## solution
61+
res <- grasps(X = X, membership = sim$membership, penalty = "lasso", crit = "BIC")
62+
plot(res)
63+
```
64+
65+
<img src="man/figures/README-unnamed-chunk-2-1.png" width="100%" />
4966

5067
## Reference
5168

35.2 KB
Loading

man/gen_prec_sbm.Rd

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)