Skip to content

Commit 560aa70

Browse files
committed
manage grouping error
1 parent 79b010a commit 560aa70

5 files changed

Lines changed: 171 additions & 97 deletions

File tree

diceplot/DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ Imports:
2626
stats,
2727
rlang,
2828
RColorBrewer,
29-
sf
29+
sf,
30+
ggrepel

diceplot/NAMESPACE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export(order_cat_b)
1010
export(perform_clustering)
1111
export(prepare_box_data)
1212
export(prepare_plot_data)
13+
export(prepare_simple_box_data)
1314
importFrom(RColorBrewer,brewer.pal)
1415
importFrom(cowplot,draw_plot)
1516
importFrom(cowplot,ggdraw)
@@ -63,6 +64,7 @@ importFrom(ggplot2,theme)
6364
importFrom(ggplot2,theme_minimal)
6465
importFrom(ggplot2,theme_void)
6566
importFrom(ggplot2,unit)
67+
importFrom(ggrepel,geom_text_repel)
6668
importFrom(grDevices,dev.off)
6769
importFrom(grDevices,pdf)
6870
importFrom(grid,unit)

diceplot/R/diceplot.R

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ dice_plot <- function(data,
231231
var_positions <- create_var_positions(z_colors, num_vars)
232232

233233
if(cluster_by_row){
234+
print("cluster by row")
235+
print(data)
234236
y_order <- order_cat_b(data, group, y, group_colors, reverse_ordering)
235237
} else {
236238
y_order <- levels(data[[y]])
@@ -243,19 +245,30 @@ dice_plot <- function(data,
243245
}
244246

245247
plot_data <- prepare_plot_data(data, x, y, z, group, var_positions, x_order, y_order)
248+
249+
# Always create box_data, but in different ways depending on group
246250
if (!is.null(group)) {
247251
box_data <- prepare_box_data(data, x, y, group, x_order, y_order)
252+
} else {
253+
box_data <- prepare_simple_box_data(data, x, y, x_order, y_order)
248254
}
249255

250256
dot_size <- calculate_dot_size(num_vars, max_dot_size, min_dot_size)
251257

252258
p <- ggplot()
253259

260+
# Add rectangles with or without group fill
254261
if (!is.null(group)) {
255262
p <- p +
256263
geom_rect(data = box_data,
257264
aes(xmin = x_min, xmax = x_max, ymin = y_min, ymax = y_max, fill = !!sym(group)),
258265
color = "grey", alpha = group_alpha, linewidth = 0.5)
266+
} else {
267+
# When group is NULL, use white boxes
268+
p <- p +
269+
geom_rect(data = box_data,
270+
aes(xmin = x_min, xmax = x_max, ymin = y_min, ymax = y_max),
271+
fill = "white", color = "grey", alpha = group_alpha, linewidth = 0.5)
259272
}
260273

261274
# Add points for z
@@ -300,7 +313,7 @@ dice_plot <- function(data,
300313
}
301314

302315
# Create custom legends only if group is provided and show legend is true
303-
if (!is.null(group) && show_legend) {
316+
if (show_legend) {
304317
combined_legend_plot <- create_custom_legends(
305318
data, z, group, z_colors, group_colors, var_positions, num_vars, dot_size
306319
)

diceplot/R/utils.R

Lines changed: 150 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,25 @@ perform_clustering <- function(data, cat_a, cat_b, cat_c) {
124124
#' @importFrom rlang sym
125125
#' @export
126126
order_cat_b <- function(data, group, cat_b, group_colors, reverse_order = FALSE) {
127-
cat_b_order <- data %>%
128-
mutate(!!sym(group) := factor(!!sym(group), levels = rev(names(group_colors)))) %>% # Reverse to match legacy code
129-
group_by(!!sym(group), !!sym(cat_b)) %>%
130-
summarise(count = n(), .groups = "drop") %>%
131-
arrange(!!sym(group), desc(count), !!sym(cat_b)) %>%
132-
pull(!!sym(cat_b)) %>%
133-
unique()
127+
if (is.null(group)) {
128+
# If group is NULL, order by count only
129+
cat_b_order <- data %>%
130+
group_by(!!sym(cat_b)) %>%
131+
summarise(count = n(), .groups = "drop") %>%
132+
arrange(desc(count), !!sym(cat_b)) %>%
133+
pull(!!sym(cat_b)) %>%
134+
unique()
135+
} else {
136+
# Original logic using group
137+
cat_b_order <- data %>%
138+
mutate(!!sym(group) := factor(!!sym(group), levels = rev(names(group_colors)))) %>%
139+
group_by(!!sym(group), !!sym(cat_b)) %>%
140+
summarise(count = n(), .groups = "drop") %>%
141+
arrange(!!sym(group), desc(count), !!sym(cat_b)) %>%
142+
pull(!!sym(cat_b)) %>%
143+
unique()
144+
}
145+
134146
if (reverse_order) {
135147
cat_b_order <- rev(cat_b_order)
136148
}
@@ -181,8 +193,17 @@ prepare_plot_data <- function(data, cat_a, cat_b, cat_c, group, var_positions, c
181193
!!sym(cat_b) := factor(!!sym(cat_b), levels = cat_b_order),
182194
x_pos = as.numeric(!!sym(cat_a)) + x_offset,
183195
y_pos = as.numeric(!!sym(cat_b)) + y_offset
184-
) %>%
185-
arrange(!!sym(cat_a), !!sym(group), !!sym(cat_b))
196+
)
197+
198+
# Arrange differently based on whether group is NULL
199+
if (!is.null(group)) {
200+
plot_data <- plot_data %>%
201+
arrange(!!sym(cat_a), !!sym(group), !!sym(cat_b))
202+
} else {
203+
plot_data <- plot_data %>%
204+
arrange(!!sym(cat_a), !!sym(cat_b))
205+
}
206+
186207
return(plot_data)
187208
}
188209

@@ -218,6 +239,11 @@ prepare_plot_data <- function(data, cat_a, cat_b, cat_c, group, var_positions, c
218239
#' @importFrom rlang sym
219240
#' @export
220241
prepare_box_data <- function(data, cat_a, cat_b, group, cat_a_order, cat_b_order) {
242+
# This function should only be called when group is not NULL, but adding a check for safety
243+
if (is.null(group)) {
244+
stop("prepare_box_data function cannot be called with group = NULL")
245+
}
246+
221247
box_data <- data %>%
222248
mutate(
223249
!!sym(cat_a) := factor(!!sym(cat_a), levels = cat_a_order),
@@ -231,6 +257,37 @@ prepare_box_data <- function(data, cat_a, cat_b, group, cat_a_order, cat_b_order
231257
y_max = as.numeric(!!sym(cat_b)) + 0.4
232258
) %>%
233259
arrange(!!sym(cat_a), !!sym(group), !!sym(cat_b))
260+
261+
return(box_data)
262+
}
263+
264+
#' @title Prepare Simple Box Data (no grouping)
265+
#' @description
266+
#' Prepares data for plotting boxes without grouping by calculating box boundaries based on category positions.
267+
#' @param data A data frame containing the variables.
268+
#' @param cat_a The name of the column representing category A.
269+
#' @param cat_b The name of the column representing category B.
270+
#' @param cat_a_order A vector specifying the order of category A.
271+
#' @param cat_b_order A vector specifying the order of category B.
272+
#' @return A data frame with box boundaries for plotting.
273+
#' @importFrom dplyr %>% mutate distinct arrange
274+
#' @importFrom rlang sym
275+
#' @export
276+
prepare_simple_box_data <- function(data, cat_a, cat_b, cat_a_order, cat_b_order) {
277+
box_data <- data %>%
278+
mutate(
279+
!!sym(cat_a) := factor(!!sym(cat_a), levels = cat_a_order),
280+
!!sym(cat_b) := factor(!!sym(cat_b), levels = cat_b_order)
281+
) %>%
282+
distinct(!!sym(cat_a), !!sym(cat_b)) %>%
283+
mutate(
284+
x_min = as.numeric(!!sym(cat_a)) - 0.4,
285+
x_max = as.numeric(!!sym(cat_a)) + 0.4,
286+
y_min = as.numeric(!!sym(cat_b)) - 0.4,
287+
y_max = as.numeric(!!sym(cat_b)) + 0.4
288+
) %>%
289+
arrange(!!sym(cat_a), !!sym(cat_b))
290+
234291
return(box_data)
235292
}
236293

@@ -270,7 +327,8 @@ calculate_dot_size <- function(num_vars, max_size, min_size) {
270327
#' @importFrom cowplot plot_grid
271328
#' @importFrom stats dist hclust
272329
#' @importFrom utils globalVariables
273-
#' @importFrom rlang sym
330+
#' @importFrom rlang sym
331+
#' @importFrom ggrepel geom_text_repel
274332
#' @export
275333
create_custom_legends <- function(data, cat_c, group, cat_c_colors, group_colors, var_positions, num_vars, dot_size) {
276334
# Create legend_data using var_positions
@@ -280,104 +338,105 @@ create_custom_legends <- function(data, cat_c, group, cat_c_colors, group_colors
280338
y = y_offset + 1
281339
)
282340

283-
# Adjust label positions using legend_data
284-
label_offsets <- legend_data %>%
285-
mutate(
286-
label_x = x + ifelse(x_offset == 0, 0.25, x_offset * 1.5), # Adjust multiplier as needed
287-
label_y = y # You can adjust y position if needed
288-
)
289-
290-
# Create the custom legend plot for cat_c
291341
custom_legend_plot <- ggplot() +
292342
geom_point(data = legend_data, aes(x = x, y = y, color = var), size = dot_size) +
293343
geom_point(data = legend_data, aes(x = x, y = y), size = dot_size + 0.5, shape = 1, color = "black") +
344+
# Replace geom_text with geom_text_repel
345+
geom_text_repel(
346+
data = legend_data,
347+
aes(x = x, y = y, label = var),
348+
size = 3.5,
349+
segment.size = 0.2,
350+
box.padding = 0.5,
351+
point.padding = 0.3,
352+
force = 1,
353+
max.overlaps = Inf
354+
) +
294355
scale_color_manual(values = cat_c_colors, name = cat_c) +
295356
theme_void() +
357+
ggtitle("Dice arrangement")+
296358
theme(
297359
legend.position = "none",
298360
plot.margin = margin(5, 5, 5, 5),
299-
aspect.ratio = 1 # Enforce square aspect ratio
300-
) +
301-
coord_fixed(ratio = 1, xlim = c(0.5, 2.5), ylim = c(0.5, 1.5), expand = FALSE) +
302-
geom_text(data = label_offsets,
303-
aes(x = label_x, y = label_y, label = var),
304-
size = 3,
305-
color = "black",
306-
hjust = 0,
307-
vjust = 0.5) +
308-
ggtitle("Dice arrangement")
309-
310-
311-
# Compute coordinate ranges
312-
ylim_min <- 0.5
313-
ylim_max <- length(group_colors) + 0.5
314-
ylim_range <- ylim_max - ylim_min
315-
316-
xlim_min <- 0.5
317-
xlim_max <- 1.5 # Keep x-axis narrow to help maintain aspect ratio
318-
xlim_range <- xlim_max - xlim_min
319-
320-
# Compute aspect ratio
321-
aspect_ratio <- ylim_range / xlim_range
322-
323-
# Create legend data for group
324-
legend_data_group <- data.frame(
325-
group = factor(names(group_colors), levels = names(group_colors)),
326-
x = 1,
327-
y = seq(length(group_colors), 1)
328-
)
361+
aspect.ratio = 1
362+
)
363+
329364

365+
330366
# Create the custom legend plot for group
331-
group_legend_plot <- ggplot() +
332-
geom_rect(
333-
data = legend_data_group,
334-
aes(
335-
xmin = x - 0.3,
336-
xmax = x + 0.3,
337-
ymin = y - 0.3,
338-
ymax = y + 0.3,
339-
fill = group
340-
),
341-
color = "grey",
342-
alpha = 0.6,
343-
linewidth = 0.5
344-
) +
345-
scale_fill_manual(values = group_colors, name = group) +
346-
theme_void() +
347-
theme(
348-
legend.position = "none",
349-
plot.margin = margin(5, 50, 5, 5), # Increase right margin for labels
350-
aspect.ratio = aspect_ratio # Set computed aspect ratio
351-
) +
352-
coord_fixed(
353-
ratio = 1, # Keep units equal on x and y axes
354-
xlim = c(xlim_min, xlim_max),
355-
ylim = c(ylim_min, ylim_max),
356-
expand = FALSE,
357-
clip = "off" # Allow labels to be drawn outside the plotting area
358-
) +
359-
geom_text(
360-
data = legend_data_group,
361-
aes(x = x + 0.4, y = y, label = group),
362-
size = 3,
363-
color = "black",
364-
hjust = 0
367+
if (!is.null(group)){
368+
# Compute coordinate ranges
369+
ylim_min <- 0.5
370+
ylim_max <- length(group_colors) + 0.5
371+
ylim_range <- ylim_max - ylim_min
372+
373+
xlim_min <- 0.5
374+
xlim_max <- 1.5 # Keep x-axis narrow to help maintain aspect ratio
375+
xlim_range <- xlim_max - xlim_min
376+
377+
# Compute aspect ratio
378+
aspect_ratio <- ylim_range / xlim_range
379+
380+
# Create legend data for group
381+
legend_data_group <- data.frame(
382+
group = factor(names(group_colors), levels = names(group_colors)),
383+
x = 1,
384+
y = seq(length(group_colors), 1)
365385
)
386+
387+
group_legend_plot <- ggplot() +
388+
geom_rect(
389+
data = legend_data_group,
390+
aes(
391+
xmin = x - 0.3,
392+
xmax = x + 0.3,
393+
ymin = y - 0.3,
394+
ymax = y + 0.3,
395+
fill = group
396+
),
397+
color = "grey",
398+
alpha = 0.6,
399+
linewidth = 0.5
400+
) +
401+
scale_fill_manual(values = group_colors, name = group) +
402+
theme_void() +
403+
theme(
404+
legend.position = "none",
405+
plot.margin = margin(5, 50, 5, 5), # Increase right margin for labels
406+
aspect.ratio = aspect_ratio # Set computed aspect ratio
407+
) +
408+
coord_fixed(
409+
ratio = 1, # Keep units equal on x and y axes
410+
xlim = c(xlim_min, xlim_max),
411+
ylim = c(ylim_min, ylim_max),
412+
expand = FALSE,
413+
clip = "off" # Allow labels to be drawn outside the plotting area
414+
) +
415+
geom_text(
416+
data = legend_data_group,
417+
aes(x = x + 0.4, y = y, label = group),
418+
size = 3,
419+
color = "black",
420+
hjust = 0
421+
)
422+
combined_legend_plot <- cowplot::plot_grid(
423+
custom_legend_plot,
424+
group_legend_plot,
425+
ncol = 1,
426+
align = 'v',
427+
rel_heights = c(2, 1)
428+
)
429+
430+
return(combined_legend_plot)
431+
}
366432
# Combine the legend plots vertically
367-
combined_legend_plot <- cowplot::plot_grid(
368-
custom_legend_plot,
369-
group_legend_plot,
370-
ncol = 1,
371-
align = 'v',
372-
rel_heights = c(2, 1)
373-
)
433+
print(custom_legend_plot)
434+
return(custom_legend_plot)
374435

375-
return(combined_legend_plot)
376436
}
377437

378438

379439

380-
381440
#' Create custom legends for the domino plot
382441
#'
383442
#' @param contrast_levels A character vector of contrast level names.

diceplot/tests/test_diceplots.R

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ create_and_plot_dice <- function(pathology_variables, cat_c_colors, title, cell_
4242
# Create dummy data
4343
set.seed(123)
4444
data <- expand.grid(CellType = cell_types, Pathway = pathways, stringsAsFactors = FALSE)
45-
45+
4646
data <- data %>%
4747
rowwise() %>%
4848
mutate(
@@ -66,7 +66,7 @@ create_and_plot_dice <- function(pathology_variables, cat_c_colors, title, cell_
6666
custom_theme = theme_minimal(),
6767
min_dot_size = min_dot_size,
6868
max_dot_size = max_dot_size
69-
)
69+
)
7070
}
7171

7272

@@ -147,5 +147,4 @@ create_and_plot_dice(
147147
pathway_groups = pathway_groups_large,
148148
min_dot_size = 1,
149149
max_dot_size = 3
150-
)
151-
150+
)

0 commit comments

Comments
 (0)