Search code examples
rplot

Correcting Maximum and minimum Y axis


I would like to display a plot in which plankton tow data is displayed in the range of 0-40 m BSL (below sea level) and core top data in the depth of 50-80 m. Of course, 0 m BSL should be at the top of the Y axis, but the code:

plankton_tow <- data.frame(DO <- c(-1.2, -0.8, -0.5, -1.5), depth = c(-10, -20, -30, -40))
core_tops <- data.frame(DO <- c(-2.0, -1.6, -1.3, -2.5), depth = c(-50, -60, -70, -80))

plankton_tow$depth <- min(plankton_tow$depth) - plankton_tow$depth
core_tops$depth <- min(core_tops$depth) - core_tops$depth


par(pty = "s")  


plot(plankton_tow$DO, plankton_tow$depth, xlim = range(c(plankton_tow$DO, core_tops$DO)), ylim = c(0, min (core_tops$depth)),
     xlab = expression(delta^18*O ~ "[‰] vs. PDB"), ylab = "Depth [m BSL]", 
     pch = 16, col = "black", xaxt = "n", yaxt = "n")
points(core_tops$DO, core_tops$depth, pch = 21, col = "black")



axis(side = 1, at = seq(min(plankton_tow$DO, core_tops$DO), max(plankton_tow$DO, core_tops$DO), by = 0.5))
axis(side = 2, at = seq(0, max(plankton_tow$depth, core_tops$depth), by = 10), labels = rev(seq(0, max(plankton_tow$depth, core_tops$depth), by = 10)))


enter image description here

As you can see, the data for the core top, for example, is at 0 m BSL and not at 50 m bsl <... I don't know why the depth resolution does not exist in this plot. I must have made some mistake that I don't see and unfortunately R doesn't show me an error message.

If I use: ylim = c( min(core_tops$depth),0. I get this: however the samples arent in the same depth. So what Im doing wrong?

enter image description here


Solution

  • I think your question is that the y-axis is not showing what you need. There are a few places where you work with seq and range and min/max, and I suspect you updated all but one or so.

    I suggest to prevent accidentally missing one (or more) of these limits/ranges, you precalculate them into variables.

    (Fixed) Sample data:

    plankton_tow <- data.frame(DO = c(-1.2, -0.8, -0.5, -1.5), depth = c(-10, -20, -30, -40))
    core_tops <- data.frame(DO = c(-2.0, -1.6, -1.3, -2.5), depth = c(-50, -60, -70, -80))
    plankton_tow$depth <- min(plankton_tow$depth) - plankton_tow$depth
    core_tops$depth <- min(core_tops$depth) - core_tops$depth
    

    Plot code. I am inferring that you want the y-axis numbers to be positive-numbers indicating negative-elevation (positive depth). If you want -30 instead of the 30 shown here, just remove the labels= part of axis(2, ..).

    xlims <- range(c(plankton_tow$DO, core_tops$DO))
    ylims <- c(min(core_tops$depth), 0)
    par(pty = "s")  
    plot(plankton_tow$DO, plankton_tow$depth,
         xlim = xlims, ylim = ylims,
         xlab = expression(delta^18*O ~ "[‰] vs. PDB"), ylab = "Depth [m BSL]", 
         pch = 16, col = "black", xaxt = "n", yaxt = "n")
    points(core_tops$DO, core_tops$depth, pch = 21, col = "black")
    axis(side = 1, at = seq(xlims[1], xlims[2], by = 0.5))
    axis(side = 2, at = seq(ylims[1], ylims[2], by = 10),
         labels = abs(seq(ylims[1], ylims[2], by = 10)))
    

    base graphics

    As a suggestion, you might find ggplot2 to be a worthy plot as well. To use it, it would help to have the data combined into one frame (with an added "source" variable).

    I'm using dplyr (and tibble) with this since they are often installed as well, but if you don't want to (or cannot) use them this can be altered to be ggplot2 only (with base R functions).

    library(dplyr)
    library(ggplot2)
    xlims <- range(c(plankton_tow$DO, core_tops$DO))
    ylims <- c(min(core_tops$depth), 0)
    bind_rows(tibble::lst(plankton_tow, core_tops), .id="source") |>
      ggplot(aes(DO, depth, shape = source)) +
      geom_point() +
      scale_shape_manual(
        name = NULL,
        values = c(plankton_tow = 16, core_tops = 21)) +
      scale_x_continuous(
        name = expression(delta^18*O ~ "[‰] vs. PDB"),
        limits = xlims, breaks = seq(xlims[1], xlims[2], by = 0.5)) +
      scale_y_continuous(
        name = "Depth [m BSL]",
        limits = ylims, breaks = seq(ylims[1], ylims[2], by = 10),
        labels = ~ abs(.)) +
      theme_minimal() +
      theme(legend.position = "bottom")
    

    ggplot of the same data

    Notes:

    • lst automatically names the objects as their object names, otherwise it is just list, so if you want to control the legend names instead of "plankton_tow", just set the names with (e.g.) bind_rows(Plankton = plankton_tow, ..., .id="source")
    • I used shape=source, you could just as easily uses color=source to different colors instead (then replacing scale_shape_manual with scale_color_manual) ... or you can use both if you really want to break them apart
    • I used theme_minimal() to better approximate the black/white austerity of base graphics; feel free to explore without this line to see what ggplot2 defaults to doing.
    • Similar to the base-graphics plot, I show positive depths; if you want -30 instead, remove the labels=~abs(.).