2

I would like to plot ONLY y-axis1 DATA (left axis, Var1, dotted line) as a log10 scale. The dotted line would therefore look higher on the y-axis and differences between 1 and 2 would be noticeable.

I have tried several things, but does not work ( I believe I am using them in the wrong order/place) such as:

+coord_trans(y='log10')--> empty plot

scale_y_continuous(trans = log10_trans(),... --> makes both Var1 and Var 2 log10

scale_y_log10(breaks = trans_breaks("log10", function(x) 10^x),labels = trans_format("log10", math_format(10^.x)))--> makes both y axis log10 and removes y-axis2 (Var2)

data<- data.frame(
      Day=c(1,2,3,1,2,3,1,2,3),
      Name=rep(c(rep("a",3),rep("b",3),rep("c",3))),
      Var1=c(1090,484,64010,1090,484,64010,1090,484,64010),
      Var2= c(4,16,39,2,22,39,41,10,3))


ggplot(data)  + 
  geom_bar(aes(fill=Name, y=Var2*1000, x=Day),stat="identity", colour="black", position= position_stack(reverse = TRUE))+
  geom_line(aes(x=Day, y=Var1),stat="identity",color="black", linetype="dotted", size=0.8)+
  geom_point(aes(Day, Var1), shape=8)+
  labs(title= "",
       x="",y=expression('Var1'))+
  scale_y_continuous(
    sec.axis=sec_axis(~./1000, name= expression(paste("Var2"))))+
  theme_classic()+
  scale_fill_grey(start = 1, end=0.1,name = "", labels = c("a", "b", "c"))

enter image description here

Ecg
  • 908
  • 1
  • 10
  • 28
  • 2
    Just as a heads up, stacked bars and log-scales might not work as you'd expect, see answer [here](https://stackoverflow.com/a/62195385/11374827). If you can, avoid it. – teunbrand Feb 09 '22 at 13:49
  • @teunbrand thanks for pointing that out. I will have a deep read this eve. However, what I would like to plot in log10 is Var1 (the dotted line). and therefore should not affect it that much? – Ecg Feb 09 '22 at 14:05

3 Answers3

2

I think the easiest way is to have the primary axis be the linear one, but put it on the right side of the plot. Then, you can have the secondary one be your log-transformed axis.

library(ggplot2)

data<- data.frame(
  Day=c(1,2,3,1,2,3,1,2,3),
  Name=rep(c(rep("a",3),rep("b",3),rep("c",3))),
  Var1=c(1090,484,64010,1090,484,64010,1090,484,64010),
  Var2= c(4,16,39,2,22,39,41,10,3))

# Max of secondary divided by max of primary
upper <- log10(3e6) / 80

breakfun <- function(x) {
  10^scales::extended_breaks()(log10(x))
}

ggplot(data)  + 
  geom_bar(aes(fill=Name, y=Var2, x=Day),
           stat="identity", colour="black", position= position_stack(reverse = TRUE))+
  geom_line(aes(x=Day, y=log10(Var1) / upper),
            stat="identity",color="black", linetype="dotted", size=0.8)+
  geom_point(aes(Day, log10(Var1) / upper), shape=8)+
  labs(title= "",
       x="",y=expression('Var1'))+
  scale_y_continuous(
    position = "right",
    name = "Var2",
    sec.axis = sec_axis(~10^ (. * upper), name= expression(paste("Var1")),
                        breaks = breakfun)
  )+
  theme_classic() +
  scale_fill_grey(start = 1, end=0.1,name = "", labels = c("a", "b", "c"))

Created on 2022-02-09 by the reprex package (v2.0.1)

teunbrand
  • 33,645
  • 4
  • 37
  • 63
  • wow great! @teunbrand this looks like what I was looking for thank you. Why are you using the log10 on the function, but then log2 within the plot code? – Ecg Feb 09 '22 at 14:27
  • if I'd like to determine the limits narrower within the sec.axis such as limits = c(0, 3E+06)? @teunbrand I got an error – Ecg Feb 09 '22 at 14:30
  • I've edited it to set a maximum. A log axis cannot start from 0, because `log(0)` is evaluated as `-Inf`. I used the `log10()` for the breaks because it gives nicer numbers than `log2()`. In the edit I used `log10()` throughout – teunbrand Feb 09 '22 at 14:55
1

Here is a custom breaks function:

br <- function(limits) {
  10^(seq(ifelse(limits[1] <= 0,
                 0,
                 trunc(log10(limits[1]))),
          trunc(log10(limits[2])),
          by = 1))}
ggplot(data)  + 
  geom_bar(aes(fill = Name, y = Var2 * 1000, x = Day),
           stat = "identity",
           colour = "black",
           position = position_stack(reverse = TRUE))+
  geom_line(aes(x=Day, y=Var1),
            stat = "identity",
            color = "black",
            linetype = "dotted",
            size = 0.8)+
  geom_point(aes(Day, Var1),
             shape = 8)+
  labs(title = "",
       x = "",
       y = expression('Var1'))+
  scale_y_continuous(
    breaks = br,
    sec.axis = sec_axis(~./1000, name= expression(paste("Var2"))))+
  theme_classic()+
  scale_fill_grey(start = 1,
                  end = 0.1,
                  name = "",
                  labels = c("a", "b", "c"))

Results aren't so pretty but you can customize the breaks as you wish.

plot

Stefano Barbi
  • 2,978
  • 1
  • 12
  • 11
  • Thanks for the answer @sbarbit seems like you have suggested an axis converted to log10, However, I must have not explained well, what I actually want is the data ploted as log10, so the line between 1-2-3 would look higher on the y axis. and the differences between a and b would be better seen. – Ecg Feb 09 '22 at 13:44
0

You absolutely should read the answer @teunbrand linked to in the comment to your question. But for the matter of displaying log values on the left and original values on the right, you can use:

tibble(Day = 1:10,
       Val1 =10*Day) %>% 
    ggplot(aes(x = Day, y = log10(Val1))) +
    geom_col() +
    scale_y_log10(name = "log(Val1)",
                  sec.axis = sec_axis(~ 10^., name = "Val1"))
Michael Dewar
  • 2,553
  • 1
  • 6
  • 22