Skip to content

Commit b686b79

Browse files
committed
Add scale_y_log10_reverse function for improved y-axis transformation
- Introduced scale_y_log10_reverse as a wrapper for log10 transformation with reversed axis, providing evenly spaced ticks and scientific notation. - Updated documentation to reflect the new function and its usage in ggplot2. - Removed the deprecated log10_reverse_trans function and its associated documentation. - Enhanced tests to validate the functionality of the new scale function.
1 parent c9690bc commit b686b79

File tree

7 files changed

+202
-61
lines changed

7 files changed

+202
-61
lines changed

NAMESPACE

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export(remove_redundancy)
2727
export(resolve_complete_confounders_of_non_interest)
2828
export(rotate_dimensions)
2929
export(scale_abundance)
30+
export(scale_y_log10_reverse)
3031
export(test_differential_abundance)
3132
export(test_differential_expression)
3233
export(test_gene_enrichment)
@@ -89,6 +90,7 @@ importFrom(dplyr,starts_with)
8990
importFrom(dplyr,summarise)
9091
importFrom(dplyr,summarise_all)
9192
importFrom(dplyr,ungroup)
93+
importFrom(ggplot2,scale_y_continuous)
9294
importFrom(lifecycle,deprecate_soft)
9395
importFrom(lifecycle,deprecate_warn)
9496
importFrom(magrittr,"%$%")
@@ -132,7 +134,6 @@ importFrom(rlang,quo_squash)
132134
importFrom(rlang,set_names)
133135
importFrom(scales,extended_breaks)
134136
importFrom(scales,label_scientific)
135-
importFrom(scales,log_breaks)
136137
importFrom(scales,trans_new)
137138
importFrom(stats,AIC)
138139
importFrom(stats,anova)

R/ggplot.R

Lines changed: 88 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,109 @@
1-
#' log10_reverse_trans
1+
2+
#' @importFrom scales trans_new
3+
#' @importFrom scales label_scientific
4+
#' @noRd
5+
#' @export
6+
log10_reverse_trans <- function() {
7+
trans <- function(x) -log10(x)
8+
inv <- function(x) 10^(-x)
9+
10+
# Custom breaks function for even spacing in transformed space
11+
breaks <- function(x) {
12+
# Get the range in transformed space
13+
trans_range <- trans(x)
14+
# Remove infinite values
15+
trans_range <- trans_range[is.finite(trans_range)]
16+
if (length(trans_range) == 0) return(numeric(0))
17+
18+
# Create evenly spaced breaks in transformed space
19+
min_trans <- min(trans_range)
20+
max_trans <- max(trans_range)
21+
even_breaks <- seq(min_trans, max_trans, length.out = 5)
22+
# Convert back to original space for labeling
23+
result <- inv(even_breaks)
24+
# Force the result to be returned
25+
return(result)
26+
}
27+
28+
# Custom format function for scientific notation
29+
format <- function(x) {
30+
scales::label_scientific(digits = 2)(x)
31+
}
32+
33+
scales::trans_new("log10_reverse", trans, inv, breaks, format = format)
34+
}
35+
36+
#' scale_y_log10_reverse
237
#'
338
#' `r lifecycle::badge("maturing")`
439
#'
5-
#' @description it perform log scaling and reverse the axis. Useful to plot negative log probabilities. To not be used directly but with ggplot (e.g. scale_y_continuous(trans = "log10_reverse") )
40+
#' @description A wrapper function that provides evenly spaced ticks with scientific notation for log10 reverse transformed y-axis. This is particularly useful for volcano plots and other plots showing p-values. The function applies a log10 transformation and reverses the axis to better visualize p-values without hard transforming the data, while maintaining the original p-value scale for interpretation. This allows you to see the full range of p-values with proper scaling while keeping the original values readable.
641
#'
7-
#' @importFrom scales trans_new
8-
#' @importFrom scales log_breaks
42+
#' @importFrom ggplot2 scale_y_continuous
43+
#' @importFrom scales label_scientific
944
#'
10-
#' @return A scales object
45+
#' @param breaks Number of breaks to display (default: 5)
46+
#' @param digits Number of digits for scientific notation (default: 2)
47+
#' @param ... Additional arguments passed to scale_y_continuous
48+
#'
49+
#' @return A ggplot2 scale object
1150
#'
1251
#' @examples
1352
#'
1453
#' library(ggplot2)
1554
#' library(tibble)
1655
#'
17-
#' tibble(pvalue = c(0.001, 0.05, 0.1), fold_change = 1:3) |>
18-
#' ggplot(aes(fold_change , pvalue)) +
19-
#' geom_point() +
20-
#' scale_y_continuous(trans = "log10_reverse")
56+
#' # Create test data
57+
#' test_data <- tibble(
58+
#' pvalue = c(0.0001, 0.001, 0.01, 0.05, 0.1, 0.5),
59+
#' fold_change = 1:6
60+
#' )
61+
#'
62+
#' # Use the wrapper function
63+
#' test_data |>
64+
#' ggplot(aes(fold_change, pvalue)) +
65+
#' geom_point() +
66+
#' scale_y_log10_reverse()
2167
#'
2268
#' @references
2369
#' Mangiola, S., Molania, R., Dong, R., Doyle, M. A., & Papenfuss, A. T. (2021). tidybulk: an R tidy framework for modular transcriptomic data analysis. Genome Biology, 22(1), 42. doi:10.1186/s13059-020-02233-7
2470
#'
2571
#' Wickham, H. (2016). ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. https://ggplot2.tidyverse.org
2672
#'
2773
#' @export
28-
log10_reverse_trans <- function() {
29-
trans <- function(x) -log10(x)
30-
inv <- function(x) 10^(-x)
31-
32-
trans_new("log10_reverse", trans, inv, log_breaks(base = 10))
74+
scale_y_log10_reverse <- function(breaks = 5, digits = 2, ...) {
75+
76+
# Function to create evenly spaced breaks for log10_reverse transformation
77+
create_even_breaks <- function(pvalues, n = breaks) {
78+
# Remove zeros and get finite values
79+
pvalues <- pvalues[pvalues > 0 & is.finite(pvalues)]
80+
81+
if (length(pvalues) == 0) return(numeric(0))
82+
83+
# Transform to log10 space
84+
trans_values <- -log10(pvalues)
85+
86+
# Create evenly spaced breaks in transformed space
87+
min_trans <- min(trans_values)
88+
max_trans <- max(trans_values)
89+
even_breaks <- seq(min_trans, max_trans, length.out = n)
90+
91+
# Convert back to original space
92+
10^(-even_breaks)
93+
}
94+
95+
# Create a custom breaks function that will be called by ggplot2
96+
breaks_func <- function(x) {
97+
create_even_breaks(x, n = breaks)
98+
}
99+
100+
# Return the scale with custom breaks and scientific notation
101+
scale_y_continuous(
102+
trans = "log10_reverse",
103+
breaks = breaks_func,
104+
labels = label_scientific(digits = digits),
105+
...
106+
)
33107
}
34108

35109
#' logit scale

man/log10_reverse_trans.Rd

Lines changed: 0 additions & 33 deletions
This file was deleted.

man/scale_y_log10_reverse.Rd

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

tests/testthat/test-utility-functions.R

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,55 @@ test_that("resolve_complete_confounders_of_non_interest works correctly", {
3232
skip("resolve_complete_confounders_of_non_interest has formula compatibility issues")
3333
})
3434

35-
# Test ggplot functions
36-
test_that("ggplot functions work correctly", {
37-
# Skip ggplot as it's not available
38-
skip("ggplot functions not available")
35+
# Test ggplot transformation functions
36+
test_that("log10_reverse_trans works correctly", {
37+
library(ggplot2)
38+
library(tibble)
39+
40+
# Test that the function returns a transform object
41+
trans_obj <- log10_reverse_trans()
42+
expect_s3_class(trans_obj, "transform")
43+
44+
# Test transformation functions
45+
test_values <- c(0.001, 0.01, 0.1, 0.5)
46+
transformed <- trans_obj$transform(test_values)
47+
expect_equal(transformed, -log10(test_values))
48+
49+
# Test inverse transformation
50+
inverse_transformed <- trans_obj$inverse(transformed)
51+
expect_equal(inverse_transformed, test_values, tolerance = 1e-10)
52+
53+
# Test breaks function
54+
breaks_result <- trans_obj$breaks(test_values)
55+
expect_type(breaks_result, "double")
56+
expect_true(length(breaks_result) > 0)
57+
})
58+
59+
test_that("scale_y_log10_reverse works correctly", {
60+
library(ggplot2)
61+
library(tibble)
62+
63+
# Test that the function returns a scale object
64+
scale_obj <- scale_y_log10_reverse()
65+
expect_s3_class(scale_obj, "ScaleContinuousPosition")
66+
67+
# Test with custom parameters
68+
scale_obj_custom <- scale_y_log10_reverse(breaks = 7, digits = 3)
69+
expect_s3_class(scale_obj_custom, "ScaleContinuousPosition")
70+
71+
# Test that it works in a plot
72+
test_data <- tibble(
73+
pvalue = c(0.0001, 0.001, 0.01, 0.05, 0.1, 0.5),
74+
fold_change = 1:6
75+
)
76+
77+
# Should not throw an error
78+
expect_no_error({
79+
p <- test_data |>
80+
ggplot(aes(fold_change, pvalue)) +
81+
geom_point() +
82+
scale_y_log10_reverse()
83+
})
3984
})
4085

4186
# Test bibliography function

tests/testthat/test-validation-utilities.R

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,21 @@ test_that("check_if_wrong_input works correctly", {
2424
})
2525

2626
# Test utility functions
27-
test_that("log10_reverse_trans works correctly", {
28-
# Skip utility functions as they're not available
29-
skip("utility functions not available")
30-
})
31-
3227
test_that("logit_trans works correctly", {
33-
# Skip utility functions as they're not available
34-
skip("utility functions not available")
28+
library(ggplot2)
29+
30+
# Test that the function returns a transform object
31+
trans_obj <- logit_trans()
32+
expect_s3_class(trans_obj, "transform")
33+
34+
# Test transformation functions
35+
test_values <- c(0.1, 0.5, 0.9)
36+
transformed <- trans_obj$transform(test_values)
37+
expect_equal(transformed, qlogis(test_values))
38+
39+
# Test inverse transformation
40+
inverse_transformed <- trans_obj$inverse(transformed)
41+
expect_equal(inverse_transformed, test_values, tolerance = 1e-10)
3542
})
3643

3744
# Test tidySummarizedExperiment functions

vignettes/introduction.Rmd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ airway |>
729729
# Plot
730730
ggplot(aes(x = logFC, y = PValue)) +
731731
geom_point(aes(color = PValue < 0.05, size = PValue < 0.05)) +
732-
scale_y_continuous(trans = tidybulk::log10_reverse_trans()) +
732+
scale_y_log10_reverse() +
733733
scale_color_manual(values = c("TRUE" = "red", "FALSE" = "black")) +
734734
scale_size_manual(values = c("TRUE" = 0.5, "FALSE" = 0.1)) +
735735
facet_wrap(~method) +
@@ -773,7 +773,7 @@ airway |>
773773
ggplot(aes(x = logFC, y = PValue)) +
774774
geom_point(aes(color = PValue < 0.05, size = PValue < 0.05)) +
775775
ggrepel::geom_text_repel(aes(label = symbol), size = 2, max.overlaps = 20) +
776-
scale_y_continuous(trans = tidybulk::log10_reverse_trans()) +
776+
scale_y_log10_reverse() +
777777
scale_color_manual(values = c("TRUE" = "red", "FALSE" = "black")) +
778778
scale_size_manual(values = c("TRUE" = 0.5, "FALSE" = 0.1)) +
779779
facet_wrap(~method, scales = "free_y") +

0 commit comments

Comments
 (0)