0

Very new programmer here. I'm struggling with this graph; I am trying to have one y axis reversed (for precipitation) and one y axis not reversed (for depth). I finally got both axes to work, but I can't figure out how to invert just one of them and the data too. The precipitation should be coming down from the top of the graph while the depth should stay how it is on the graph I shared here.

enter image description here

Here is what I tried:

ggp1 <-ggplot(BeachSensors) + geom_bar(aes(x=Date, y=Precip),stat="identity", fill="cyan",colour="#006000") + scale_y_reverse()
ggp1
ggp2 <- ggp1 + geom_line(aes(x=Date, y=CorrDepth, color=Sensor),stat="identity",size=1)+
labs(title= "GLSM Precipitation and Depth",
x="Date",y="Precipitation (in.)")+
scale_y_continuous(sec.axis=sec_axis(~.*2,name="Depth (ft.)")) + theme_minimal()

But I kept either inverting both of the y axes at the same time, which is not what I want.

jpsmith
  • 11,023
  • 5
  • 15
  • 36
  • 2
    Welcome to SO, hollyrose54! Questions on SO (especially in R) do much better if they are reproducible and self-contained. By that I mean including sample representative data (perhaps via `dput(head(x))` or building data programmatically (e.g., `data.frame(...)`), possibly stochastically) (as well as the code and expected output, as you've provided here). Refs: https://stackoverflow.com/q/5963269, [mcve], and https://stackoverflow.com/tags/r/info. Thanks! – r2evans Jan 31 '23 at 20:40
  • (Note that it doesn't need to be _real_ data, just "close enough" so that if we use it, you can project our code to your real data.) – r2evans Jan 31 '23 at 20:41
  • Thank you so much for the information! Apologies if I overlooked that before posting, but I appreciate it very much! – hollyrose54 Feb 01 '23 at 06:04

1 Answers1

1

The "trick" (and often nightmares of inverting algebraic equations in high school) is knowing how to change the transforms for sec_axis, and knowing that you need to change the raw data itself.

I'm going to assume your data is in a "wide" format, looking somewhat like this:

set.seed(42)
dat <- data.frame(precip = runif(50, 0, 1.5)) |>
  transform(
    time = 1:50,
    precip = ifelse(runif(50) < 0.8, 0, precip),
    sensor = sample(c("inside", "outside"), 50, replace = TRUE)
  ) |>
  transform(depth = 3.6 + cumsum(precip) - time/10)
head(dat)
#   precip time  sensor depth
# 1      0    1 outside   3.5
# 2      0    2 outside   3.4
# 3      0    3  inside   3.3
# 4      0    4 outside   3.2
# 5      0    5  inside   3.1
# 6      0    6 outside   3.0

From here, we need to know how to algebraically convert depth to the correct location and scale of the precip data.

The conversion is a "simple" scaling, meaning we need to adjust it to be completely within [0,1] and then adjust to the new scale. Using some prep objects,

rngdepth <- range(dat$depth)
diffdepth <- diff(rngdepth)
maxprecip <- max(dat$precip)
diffprecip <- diff(range(dat$precip))

We now have a simple relationship and the inversion. The two formulas we're interested in are the first and last:

y = maxprecip - diffprecip * (depth - rngdepth[1]) / diffdepth
maxprecip - y = diffprecip * (depth - rngdepth[1]) / diffdepth
diffdepth * (maxprecip - y) = diffprecip * (depth - rngdepth[1])
diffdepth * (maxprecip - y) / diffprecip = depth - rngdepth[1]
diffdepth * (maxprecip - y) / diffprecip + rngdepth[1] = depth

I prefer to use ~-function transforms in the data, so that the original frame is not encumbered (confusingly, sometimes) with the variables. Here's the plotting code:

ggplot(dat, aes(x = time)) +
  geom_col(aes(y = precip)) +
  geom_line(
    aes(x = time, y = depth2, color = sensor, group = sensor),
    data = ~ transform(., depth2 = maxprecip - diffprecip * (depth - rngdepth[1]) / diffdepth)
  ) +
  scale_y_reverse(
    name = "Precipitation",
    sec.axis = sec_axis(
      ~ diffdepth * (maxprecip - .) / diffprecip + rngdepth[1],
      name = "Depth"
    )
  )

ggplot2 with primary axis inverted, secondary axis upright and scaled

r2evans
  • 141,215
  • 6
  • 77
  • 149
  • This is amazing! I have so much to learn about coding. I can't wait to try this with my data. Thank you so much! – hollyrose54 Feb 01 '23 at 06:05