0

I want to plot a diagram with a log scales y axis:

data <- data.frame(x = seq_len(5), y = c(2,1,100,500,30))
ggplot(data) + aes(x,y) + geom_col() + scale_y_log10()

But because the horizontal axis always crosses the vertical axis at y = 1, the bar for y = 1 is never drawn.

enter image description here

I know that log(1) = 0, but can I set the plot base to 0.1 to let the bar start below 1?

Stefan L.
  • 65
  • 10
  • We can cheat a bit: `ggplot(data) + aes(x, y + 0.1) + geom_col() + scale_y_log10()` – zx8754 Nov 03 '20 at 10:00
  • I think I'm missing the point here. The graph is correct: the values on the Y axis are log-transofrmed, hence zero becomes 1; `log10(1)` is zero, so it's correct you can't see bar 2. What's your goal? – Edo Nov 03 '20 at 10:00
  • Related, possible duplicate https://stackoverflow.com/q/40219639/680068 – zx8754 Nov 03 '20 at 10:02
  • 1
    One option is to force a line round the bars - e.g. `geom_col(colour = "grey20")`, so that you at least get a line at y=1. – Andrew Gustar Nov 03 '20 at 10:03
  • 1
    Another related post https://stackoverflow.com/q/41849951/680068 – zx8754 Nov 03 '20 at 10:06
  • I think the only way without doing much of programming is to set the color as @AndrewGustar wrote. I also have some histograms, so "cheating" is not possible without doing all the calculation by hand. – Stefan L. Nov 03 '20 at 11:11
  • @StefanL. no, that's not true, because the y scale will take a label transforming function. See my answer to show this working with `geom_histogram` – Allan Cameron Nov 03 '20 at 13:26

2 Answers2

1

An alternative solution is to place the bottom of the bars at -Inf, so that the log10(1) still shows up. This is a bit tricky, because you have to reparameterise the bars as rectangles and get the geom to understand that the -Inf is after scale transformation.

library(ggplot2)

data <- data.frame(x = seq_len(5), y = c(2,1,100,500,30))

ggplot(data) + 
  geom_rect(
    aes(xmin = x - 0.45, xmax = x + 0.45,
        ymin = stage(1, after_scale = -Inf), ymax = y)
  ) +
  scale_y_log10()

Created on 2020-11-03 by the reprex package (v0.3.0)

teunbrand
  • 33,645
  • 4
  • 37
  • 63
  • It's not only geom_col I want to print, but also histograms. Your solution is drawing the boxes by hand, but if I want to use the histogram calculation, this won't work. I hoped for a small parameter I didn't find so far. – Stefan L. Nov 03 '20 at 11:14
1

Can't you just multiply the values of y by 10 but divide the labels by the same amount?

ggplot(data) + aes(x, y * 10) +  geom_col() + 
  scale_y_log10(labels = function(x) x/10, name = "y")

enter image description here

You could do the same with a histogram:

set.seed(2)
ggplot(data.frame(x = rnorm(1000)), aes(x)) + 
  geom_histogram(aes(y = ..count.. * 10), color = "black", fill = "gold") +
  scale_y_log10(labels = function(x) x/10, name = "count")

enter image description here

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87