Mirrored (or "centered") log-scale in ggplot2

Viewed 50

For a meta-analysis, I am creating a forest plot that depicts ratios (on the x-axis) per case study (on the y-axis). I have many values that are close to 1 (e.g., ranging from ca. 0.75 - 1.5) and very few that are either very large (e.g., 100) or very small (e.g., 0.001). My major issue is that I want the (subtle) differences between the many values around 1 to be visible well, while I do not need the extreme values to be as far apart as if I plotted them on a normal, continuous scale. I am using using ggplot2. In my first attempt, I converted the x-axis to a log-scale using the scale_x_continuous(trans = "log10") argument. While this makes differences between the values close to, but larger than 1 clear, the opposite is the case for values <1, where differences are not really visible. I have added the tickmarks to the following plot so you can hopefully get what I mean.

What I would like to have is something like a "mirrored" log-scale, centered around 1. That is, the log10 transformation should be kept for all values >1, but I want a "reversed" log-transformation (i.e., a sqrt-transformation?) for everything <1 (i.e., the left side of the plot). So that (hopefully) overall, the values around +- 1 are more disentangled.

Any idea how to do this in ggplot2? I'd like to transform only the scale not the ratio values themselves, as they have meaning for interpretation.

Here is a reproducible example of what I've tried so far:

    library(scales)

SampleData <- data.frame(letters[1:10], c(0.1, 0.95, 1.3, 2, 99, 0.88, 0.001, 1.15, 2.5, 0.75))
colnames(SampleData) <- c("CaseID","Ratio")

SampleData %>% ggplot(aes(x = Ratio, y = CaseID)) + 
  geom_point() +
  geom_vline(xintercept = 1) +
  theme_bw() +
  scale_x_continuous(trans = "log10") +
  annotation_logticks(sides = "b")

Resulting in the following plot.

1 Answers

This answer isn't really an answer at all, just an alternative to the problem. It seems that you can avoid complicated transformations if you zoom into the region of data you want to highlight. You can do this with ggforce::facet_zoom().

library(scales)
library(ggplot2)
library(ggforce)

SampleData <- data.frame(letters[1:10], c(0.1, 0.95, 1.3, 2, 99, 0.88, 0.001, 1.15, 2.5, 0.75))
colnames(SampleData) <- c("CaseID","Ratio")

ggplot(SampleData, aes(x = Ratio, y = CaseID)) + 
  geom_point() +
  geom_vline(xintercept = 1) +
  theme_bw() +
  scale_x_continuous(trans = "log10") +
  facet_zoom(xlim = c(-0.5, 0.5)) +
  annotation_logticks(sides = "b")

Created on 2022-08-12 by the reprex package (v2.0.0)

Related