Chiara
Chiara

Reputation: 33

How can I plot two graphs in one plot with a secondary y-axis with different y-axis scales and DateTime data?

I want to merge two plots in R to create one plot with a secondary Y axis for my Tides data. The problem is that I have Temperature data for every hour, but the Tide data is only for time points at low and high tide, so there are missing values in the dataset. In the individuals plots I have overcome this problem using

geom_line(data=m_tide[!is.na(m_tide$Tides),]

for Tides data. However when I want to plot the two in one graph with a secondary axis this causes problems. This is a subset of my data:

Subset of data

The values for the different y-axis are different. Temperature ranges from ~23 to 45 and Tidal height ranges from ~ 0.4 to 2.55. My x-axis is a asPOSIXct Datetime object.

To make two separate plots I used:

ylab <- expression("Temperature " ( degree*C))
(mtide_temp <- ggplot(m_tide, aes(x=Date_Time, y=Temperature)) +
  geom_line(color="#33A02C") + 
  labs(x="", y=ylab) +
  scale_x_datetime(date_breaks="1 day", date_labels = "%d %b %y") +
  theme_bw() +
  theme(axis.text.x=element_text(angle=60, hjust=1)) +
  scale_y_continuous(limits = c(20, 45), breaks = seq(20, 45, by = 5)))

Temperature data

My Tidal data:

ylab <- "Tide height (m)"
ggplot(m_tide, aes(x=Date_Time, y=Tides)) +
  geom_line(data=m_tide[!is.na(m_tide$Tides),], color="steelblue") + 
  geom_point(na.rm=TRUE, color=“steel blue”) +
  scale_x_datetime(date_breaks="1 day", date_labels = "%d %b %y") +
  labs(x="", y=ylab, title="Mangrove Tides") +
  theme_bw() +
  theme(axis.text.x=element_text(angle=60, hjust=1))

Tidal data

I have tried using scale_y_continuous(sec.axis = sec_axis(~ ., name = ylab, breaks = seq(0, 2.5, by = 0.5))) to create a second y-axis, but I haven’t been able to incorporate this successfully in my ggplot code.

This is what I got so far but the secondary scale isn’t correct and Tide data isn’t plotted correctly either

scale=18
(temp_tide <- ggplot(m_tide, aes(x=Date_Time, y=Temperature)) +
  geom_line(aes(color="Temperature")) +
  geom_line(data=m_tide[!is.na(m_tide$Tides),]) + #doesn't plot Tide at correct y-axis values
  labs(x="", y="Temperature", color="") +
  scale_color_manual(values=c("#33A02C", "grey50")) +
  scale_y_continuous(sec.axis = sec_axis(~ ./scale, name = "Tidal height (m)", breaks = seq(0, 2.5, by = 0.5))))

Merged plots attempt

Any suggestions on how I can plot these two graphs in one plot with a secondary y-axis for Tide height (m)? Any help would be greatly appreciated! Many thanks!

Upvotes: 1

Views: 414

Answers (1)

Alberson Miranda
Alberson Miranda

Reputation: 1430

First of all, in order to get really useful answers you should post your data (dput() is fine). From the spec of data from the picture, I could only reproduce a tiny portion of the plot.

Anyway, sec.axis() does nothing to your data. It only affects your secundary axis labels. So dividing by scale only changed secundary axis labels.

For your data to be plotted together, you should bring Tidal data up to the same level as Temperature (or vice-versa), thus multiplying it by your scale.

Another option is to plot them side by side, fixing only x axis (I like this one way better).

library(ggplot2)

# data
data = structure(list(V1 = c(7038, 7039, 7040, 7041, 7042, 7043, 
7044, 7045, 7046, 7047, 7048, 7049, 7050, 7051, 7052, 7053, 7054, 
7055, 7056, 7057), Date_Time = structure(c(1669421760, 1669425360, 
1669428960, 1669432560, 1669436160, 1669439760, 1669443360, 1669446960, 
1669450560, 1669454160, 1669457760, 1669461360, 1669464960, 1669468560, 
1669472160, 1669475760, 1669479360, 1669482960, 1669486560, 1669490160
), class = c("POSIXct", "POSIXt"), tzone = "UTC"), Temperature = c("28.53", 
"28.18", "26.63", "26.07", "25.90", "26.15", "26.39", "27.57",
"29.00", "29.33", "29.70", "29.68", "29.73", "30.06", "29.95",
"29.48", "29.13", "28.93", "27.10", "28.21"), mV = c("-51.85",
"-44.47", "-62.28", "-64.02", "-64.36", "-64.25", "-64.13", "-60.67",
"-73.30", "-77.77", "-79.58", "-78.24", "-76.88", "-79.11", "-82.63",
"-77.89", "-58.67", "-49.36", "-65.89", "-55.66"), pH = c("7.74", 
"7.61", "7.92", "7.95", "7.96", "7.96", "7.95", "7.89", "8.10",
"8.18", "8.21", "8.18", "8.16", "8.20", "8.26", "8.18", "7.85",
"7.69", "7.98", "7.80"), Tides = c(NA, NA, NA, NA, "0.40", NA,
NA, NA, NA, NA, NA, "2.60", NA, NA, NA, NA, NA, "1.22", NA, NA
)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA,
-20L))

# scale
scale = 18

# format
m_tide = within(data, {
    Temperature = as.numeric(Temperature)
    mV = as.numeric(mV)
    pH = as.numeric(pH)
    Tides_2 = as.numeric(Tides)
    Tides = as.numeric(Tides) * scale
})

tidyr::pivot_longer(m_tide, cols = c(-V1, -Date_Time)) |>
    subset(name %in% c("Temperature", "Tides")) |>
    na.omit() |>
    ggplot(aes(x = Date_Time, group = name, y = value, color = name)) +
    geom_line() +
    labs(x = "", y = "Temperature", color = "") +
    scale_y_continuous(
        sec.axis = sec_axis(
            ~ . / scale,
            name = "Tidal height (m)",
            breaks = seq(0, 2.5, by = 0.5)
        )
    )


tidyr::pivot_longer(m_tide, cols = c(-V1, -Date_Time)) |>
    subset(name %in% c("Temperature", "Tides_2")) |>
    na.omit() |>
    ggplot(aes(x = Date_Time, y = value, color = name)) +
    geom_line() +
    labs(x = "", y = "Temperature", color = "") +
    facet_grid(vars(name), scales = "free_y")

Created on 2023-03-28 with reprex v2.0.2

Upvotes: 0

Related Questions