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.
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.
The "trick" (and often nightmares of inverting algebraic equations in high school) is knowing how to change the trans
forms 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"
)
)