I am having trouble when placing a secondary axis to a plot with ggplot2
. Specifically, the secondary axis maps on backwards to what it should be. I am unsure if I am using the sec.axis argument incorrectly, if this is a problem with the transformation to the primary axis data, or an odd bug.
library(ggplot2)
library(VGAM)
#dput(x) # create reproducible data set
structure(list(DATE = structure(c(15188, 15233, 15270, 15291,
15320, 15380, 15426, 15481, 15510, 15547, 15553, 15156, 15188,
15233, 15289, 15426, 15431, 15481, 15510, 15547, 15188, 15233,
15270, 15291, 15340, 15380, 15426, 15431, 15510, 15553, 15156,
15188, 15233, 15270, 15291, 15380, 15426, 15431, 15510, 15521,
14908, 14943, 14994, 15028, 15052, 15082, 15104, 15147, 15174,
15202, 15231, 15264, 15273, 14908, 14943, 14992, 15028, 15050,
15082, 15103, 15147, 15174, 15202, 15237, 15272, 15273), class = "Date"),
JULIAN = c(578, 623, 660, 681, 710, 770, 816, 871, 900, 937,
943, 546, 578, 623, 679, 816, 821, 871, 900, 937, 578, 623,
660, 681, 730, 770, 816, 821, 900, 943, 546, 578, 623, 660,
681, 770, 816, 821, 900, 911, 298, 333, 384, 418, 442, 472,
494, 537, 564, 592, 621, 654, 663, 298, 333, 382, 418, 440,
472, 493, 537, 564, 592, 627, 662, 663), tempkt = c(38.2493118575297,
38.8918139130956, 38.9751719525914, 38.9255342604126, 39.3289327383671,
39.2502632853114, 38.4917383006476, 38.085196933948, 37.9534931405596,
38.0571510040783, 37.8609414814348, 41.0441867847656, 41.2983574639028,
41.9484899893221, 42.2016623398487, 42.2929040412033, 42.2093300154886,
41.5844615902843, 40.9536690489977, NaN, 39.7920269821338,
39.592156547337, 39.61233495346, 39.6624446808614, 39.8342150883199,
40.3918668247933, 40.2143769350208, 40.2393349250642, 39.8234837693704,
39.742700709588, 40.424224969676, 40.4451990799614, 40.8109263766474,
40.9865924998806, 41.0375724497903, 41.2189808187393, 41.3206162959404,
40.9766042214562, 40.4577779507897, 40.382158701417, 41.8201031347131,
41.8147160575188, 41.6767569469964, 41.658527312322, 41.6448016266584,
41.6420919537599, 41.5754495299616, 41.3110244532269, 41.3494251124613,
41.4485458187588, 41.546733896547, 41.4299365483899, 41.0628872985866,
41.9901884386202, 42.1042719644897, 42.0470007228451, 42.0555023596041,
41.9215569534753, 41.7497755339366, 41.401267252905, 40.9710848825845,
40.9252447192775, 41.1847858804725, 41.5180158973558, 41.6932841697949,
41.625926125789), SITE = c("hver", "hver", "hver", "hver",
"hver", "hver", "hver", "hver", "hver", "hver", "hver", "st14",
"st14", "st14", "st14", "st14", "st14", "st14", "st14", "st14",
"st6", "st6", "st6", "st6", "st6", "st6", "st6", "st6", "st6",
"st6", "st9", "st9", "st9", "st9", "st9", "st9", "st9", "st9",
"st9", "st9", "st7", "st7", "st7", "st7", "st7", "st7", "st7",
"st7", "st7", "st7", "st7", "st7", "st7", "oh2", "oh2", "oh2",
"oh2", "oh2", "oh2", "oh2", "oh2", "oh2", "oh2", "oh2", "oh2",
"oh2")), row.names = c(NA, -66L), class = "data.frame")
#function to transform tempkt
overkt_to_C <<- Vectorize(function(x) {
VGAM::reciprocal(x*(8.61733*10^-5))-273.15})
#applying the function to an object to check ouput
x$tempC = overkt_to_C(x$tempkt)#new transformed variable
x$measure = rnorm(nrow(x))#random data row
Now when I plot the original variable tempkt
against the new variable tempC
created with the overkt_to_C
function it shows the transformation does what it is supposed to:
ggplot(x, aes(x = tempkt, y = tempC)) + geom_line(size = 2) +
labs(x = "Boltzmann Temperature (1/kt)", y = "Temperature C")
Importantly for the question, there is a negative relationship, x = 38 corresponds to y = ~35, x = 42 corresponds to y = ~0. However, when I try to use the overkt_to_C
function to transform tempkt
onto a secondary axis showing tempC
the transformation doesn't show this negative relationship. Rather, it is positive. x = 38 on the primary (bottom) axis corresponds to ~0 on the secondary (top) axis rather than ~35:
ggplot(x, aes(x = tempkt, y = measure)) +
scale_x_continuous(name = "Boltzmann Temperature", sec.axis = sec_axis(~overkt_to_C(.), name = expression("Temperature"~degree*"C")))
I have tried reversing the direction for either of them multiple ways, which if they do anything they reverse both axes:
ggplot(x, aes(y = tempkt, x = measure)) + coord_flip() +
scale_y_continuous(name = "Boltzmann Temperature", trans = 'reverse',
sec.axis = sec_axis(~overkt_to_C(.), name = expression("Temperature"~degree*"C")))
I tried the suggestion from the answer to this question :ggplot2: Reversing secondary continuous x axis
ggplot(x, aes(y = tempkt, x = measure)) + coord_flip() +
scale_y_continuous(name = "Boltzmann Temperature", trans = 'reverse',
sec.axis = sec_axis(~(33.3538 - overkt_to_C(.)), name = expression("Temperature"~degree*"C")))##33.353 is max x$tempC
Which does an odd thing and only slightly shifts the top axis. The closest I can get is with this, which maps negative values close to expected (this could just be coincidence):
ggplot(x, aes(x = tempkt, y = measure)) +
scale_x_continuous(name = "Boltzmann Temperature", trans = 'reverse',
sec.axis = sec_axis(~(-33.3538 + overkt_to_C(.)), name = "Temperature C"))
Edit: Below is a close approximation (created with the code directly above) to what the expected output should be with an important caveat: The values are negative, not positive as they should be, as shown in the first figure. I don't know if this is a coicidence. But the expectation is that the top axis should map as the relationship shown in the first figure, which it currently does not for unknown reasons.
And in a desperate attempt, took some advice from DJ Casper trying the cha cha slide method--"reverse-reverse":
ggplot(x, aes(y = tempkt, x = measure)) + coord_flip() +
scale_y_reverse(name = "Boltzmann Temperature", trans = 'reverse',
sec.axis = sec_axis(~overkt_to_C(.), name = expression("Temperature"~degree*"C")))
Any ideas on why this is happening, why the workaround of subtracting the max tempC
value doesn't produce the desired results, and/or potential workarounds would be much appreciated.
I submitted the issue on Github, but here's a manual workaround. I simplified your transformation function, but it should work the same regardless, as long as you provide the inverse as well.
Generate some fake data
Manually calculate breaks and backconvert
Here we take the
kt
data and convert it to C using the function, then usescales::extendedbreaks()
to figure out where the breaks would be if the original data was in C.Then we back-convert those pretty numbers into ugly un-round kt numbers. That way
ggplot
knows where to put the breaks in coordinate space, and we have the nice round labels ready to go.Make the figure
Since we handled the transformation manually, we just want to use
dup_axis
and lie to it about how to label the numbers.