user33993
user33993

Reputation: 65

ggplot dual reversed y axis and geom_hline intercept calculation

I have created a line graph in ggplot2 with two y axes, and want only one dataset (blue) plotted on a reversed axis and want the other dataset (red) plotted on a different scale from the first. However, the code I am working with reverses both axes, and although the second y axis has been coded to have a different scale the second dataset (red) is being plotted using the scale of the first y axis. Furthermore I have created a line (green) for which I have to determine where the blue line intercepts it. I know the latter part of this question has been asked before and was answered, however it was noted in that post that the solution doesn't actually work. Any input would be helpful! Thank you! I've provided a sample dataset as mine is too large to recreate.

time<-c(1,2,3,4,5,6,7,8,9,10)
height<-c(100,330,410,570,200,270,230,390,400,420)
temp<-c(37,33,14,12,35,34,32,28,26,24)
tempdf<-data.frame(time,height,temp)

makeplot<-ggplot(tempdf,aes(x=time)) + geom_line(aes(y=height),color="Blue") 
    + geom_line(aes(y=temp),color="Red")+
    scale_y_continuous(sec.axis=sec_axis(~./100,name = 
    "Temperature"),trans="reverse")+
    geom_hline(aes(yintercept=250), color="green")

enter image description here

Upvotes: 2

Views: 1528

Answers (3)

Axeman
Axeman

Reputation: 35242

Another alternative is a path plot:

ggplot(tempdf, aes(height, temp)) + 
  geom_path() + 
  geom_point(aes(fill = time), size = 8, shape = 21) + 
  geom_text(aes(label = time)) + 
  viridis::scale_fill_viridis()

enter image description here

Upvotes: 0

neilfws
neilfws

Reputation: 33782

Ignoring the intersection of lines problem for now, here are a couple of alternatives to dual axes. First, facets:

library(tidyverse)
library(scales)
tempdf %>% 
  # convert height to depth
  mutate(height = -height) %>% 
  rename(depth = height) %>% 
  gather(key, value, -time) %>% 
  ggplot(aes(time, value)) + 
    geom_line() + 
    facet_grid(key ~ ., scales = "free_y") + 
    scale_x_continuous(breaks = pretty_breaks()) +
    theme_bw()

enter image description here

Second, use coloured points to indicate temperature at each depth:

tempdf %>% 
  mutate(height = -height) %>% 
  rename(depth = height) %>% 
  ggplot(aes(time, depth)) + 
    geom_line() + 
    geom_point(aes(color = temp), size = 3) + 
    geom_hline(yintercept = -250, color = "blue") +
    scale_color_gradient2(midpoint = 25, 
                          low = "blue", 
                          mid = "yellow", 
                          high = "red") + 
    scale_x_continuous(breaks = pretty_breaks()) + 
    theme_dark()

enter image description here

Upvotes: 1

Jan Boyer
Jan Boyer

Reputation: 1580

ggplot will only do 1:1 axis transformations, and if it flips one axis, will flip both, so you need to figure out an equation to translate your axes. Multiplying (or dividing) by a negative flips your temperature axis back to a standard increasing scale. These two equations worked to get the sample data you had on the same scale.

height = temp*(-10) + 600
temp = (height - 600)/(-10)

Now, you can incorporate the equations into your plot code, the first to translate the temperature data into numbers that fit on the height scale, the second to translate your secondary axis numbers to a scale that shows temperature.

makeplot<-ggplot(tempdf,aes(x=time)) + 
  geom_line(aes(y=height),color="blue") + 
  geom_line(aes(y = (temp*(-10)) + 600), color="red")+
  scale_y_continuous(sec.axis=sec_axis(~(.-600)/(-10),name = 
                                     "Temperature"),trans="reverse")+
  geom_hline(aes(yintercept=250), color="green")
makeplot

enter image description here

Upvotes: 3

Related Questions