Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dual y axis (second axis) use in ggplot2

Tags:

r

ggplot2

I come to encounter a problem that using two different data with the help of second axis function as described in this previous post how-to-use-facets-with-a-dual-y-axis-ggplot.

I am trying to use geom_point and geom_bar but the since the geom_bar data range is different it is not seen on the graph.

Here is what I have tried;

point_data=data.frame(gr=seq(1,10),point_y=rnorm(10,0.25,0.1))
bar_data=data.frame(gr=seq(1,10),bar_y=rnorm(10,5,1))

library(ggplot2)



sec_axis_plot <- ggplot(point_data, aes(y=point_y, x=gr,col="red")) +  #Enc vs Wafer
geom_point(size=5.5,alpha=1,stat='identity')+
geom_bar(data=bar_data,aes(x = gr, y = bar_y, fill = gr),stat = "identity") +
scale_y_continuous(sec.axis = sec_axis(trans=~ .*15,
                                         name = 'bar_y',breaks=seq(0,10,0.5)),breaks=seq(0.10,0.5,0.05),limits = c(0.1,0.5),expand=c(0,0))+

facet_wrap(~gr, strip.position = 'bottom',nrow=1)+
theme_bw()

as it can be seen that bar_data is removed. Is is possible to plot them together in this context ??

thx

enter image description here

like image 376
Alexander Avatar asked Oct 10 '17 17:10

Alexander


1 Answers

You're running into problems here because the transformation of the second axis is only used to create the second axis -- it has no impact on the data. Your bar_data is still being plotted on the original axis, which only goes up to 0.5 because of your limits. This prevents the bars from appearing.

In order to make the data show up in the same range, you have to normalize the bar data so that it falls in the same range as the point data. Then, the axis transformation has to undo this normalization so that you get the appropriate tick labels. Like so:

# Normalizer to bring bar data into point data range. This makes
# highest bar equal to highest point. You can use a different
# normalization if you want (e.g., this could be the constant 15
# like you had in your example, though that's fragile if the data
# changes).
normalizer <- max(bar_data$bar_y) / max(point_data$point_y)


sec_axis_plot <- ggplot(point_data,
                        aes(y=point_y, x=gr)) +

  # Plot the bars first so they're on the bottom. Use geom_col,
  # which creates bars with specified height as y.
  geom_col(data=bar_data,
           aes(x = gr,
               y = bar_y / normalizer)) + # NORMALIZE Y !!!

  # stat="identity" and alpha=1 are defaults for geom_point
  geom_point(size=5.5) +

  # Create second axis. Notice that the transformation undoes
  # the normalization we did for bar_y in geom_col.
  scale_y_continuous(sec.axis = sec_axis(trans= ~.*normalizer,
                                         name = 'bar_y')) +
  theme_bw()

This gives you the following plot:

enter image description here

I removed some of your bells and whistles to make the axis-specific stuff more clear, but you should be able to add it back in no problem. A couple of notes though:

  • Remember that the second axis is created by a 1-1 transformation of the primary axis, so make sure they cover the same limits under the transformation. If you have bars that should go to zero, the primary axis should include the untransformed analogue of zero.

  • Make sure that the data normalization and the axis transformation undo each other so that your axis lines up with the values you're plotting.

like image 118
Andrew Milligan Avatar answered Sep 21 '22 01:09

Andrew Milligan