Stacking multiple plots, vertically with the same x axis but different Y axes in R
Solution 1
If you want to be old-fashioned you can use lattice
. Unlike @aaronwolen I assumed there was a missing time
variable in the data set, so I made one up:
dt$time <- seq(nrow(dt))
library(reshape2)
mm <- melt(subset(dt,select=c(time,DEPTH,X,Y,Z)),id.var="time")
library(lattice)
xyplot(value~time|variable,data=mm,type="l",
scales=list(y=list(relation="free")),
layout=c(1,4))
Solution 2
I agree with @PaulHiemstra, ggplot2 is the way to go.
Assuming Smooth.Vert.Speed
is the common x-axis variable against which you want to plot DEPTH
, X
, Y
and Z
...
library(ggplot2)
library(reshape2)
# Add time variable as per @BenBolker's suggestion
dt$time <- seq(nrow(dt))
# Use melt to reshape data so values and variables are in separate columns
dt.df <- melt(dt, measure.vars = c("DEPTH", "X", "Y", "Z"))
ggplot(dt.df, aes(x = time, y = value)) +
geom_line(aes(color = variable)) +
facet_grid(variable ~ ., scales = "free_y") +
# Suppress the legend since color isn't actually providing any information
opts(legend.position = "none")
Solution 3
Just to be different, let me mention a solution involving neither lattice nor ggplot2 -- I posted this to Romain's R Graph Gallery a few years back as entry 65 with the code here. It just stacks the graphs up, using par()
settings to keep them stacked.
Note that the vertical sizes are different by choice, they could easily be of the same height as well.
Solution 4
I've actually figured out another interesting way of doing this with the zoo library:
library(zoo)
z <- with(dt, zoo(cbind(DEPTH, X, Y, Z),as.POSIXct(time)))
plot.zoo(z, ylab=c("Depth (m)", "Pitch Angle (degrees)", "Swaying Acceleration (m/s^2)", "Heaving Acceleration (m/s^2)"), col=c("black", "blue", "darkred", "darkgreen"),
xlab = c("Time"), lwd=2, ylim=list((rev(range(dt$DEPTH))), c(-90,90), c(-10,10), c(-10,10)))
So within a zoo plot you can create new axis labels as a list form and all plots can have different colours.
Jojo
Updated on February 03, 2022Comments
-
Jojo over 2 years
I have a data.frame with multiple time series vectors against a date:time vector. I would like to plot all of the relevant vectors, vertically stacked on separate graphs with the same X axis but unique Y axes. A graph similar to this one:
my data looks like this:
dt <- structure(list(DEPTH = c(156, 156.5, 157.4, 158.15, 158.8, 159.2, 159.75, 160.35, 160.85, 161.1, 161.6, 162.05, 162.5, 162.65, 163.15, 163.45, 163.55, 163.8, 163.65, 163.75, 163.8, 163.8, 163.75, 164.45, 164.8, 165.35, 165.65, 165.75, 166.1, 166.75, 167, 167.2, 167.65, 168, 168.8, 169.3, 169.7, 170.2, 170.65, 170.9, 171.45, 171.65, 172, 172.1, 172.25, 173, 173.4, 173.9, 174.2, 174.6, 175, 175.25, 175.45, 175.9, 176.25, 176.7, 177, 177.15, 177.5, 178, 178.5, 179.05, 179.2, 180.7, 181.05, 181.25, 181.5, 181.7, 182.1, 182.3, 182.35, 182.75, 183.1, 183.65, 184.3, 184.6, 185.1, 185.15, 185.3, 185.15, 185.25, 185.3, 185.15), Smooth.Vert.Speed = c(-0.550000000000011, -0.5, -0.900000000000006, -0.75, -0.650000000000006, -0.399999999999977, -0.550000000000011, -0.599999999999994, -0.5, -0.25, -0.5, -0.450000000000017, -0.449999999999989, -0.150000000000006, -0.5, -0.299999999999983, -0.100000000000023, -0.25, 0.150000000000006, -0.0999999999999943, -0.0500000000000114, 0, 0.0500000000000114, -0.699999999999989, -0.350000000000023, -0.549999999999983, -0.300000000000011, -0.0999999999999943, -0.349999999999994, -0.650000000000006, -0.25, -0.199999999999989, -0.450000000000017, -0.349999999999994, -0.800000000000011, -0.5, -0.399999999999977, -0.5, -0.450000000000017, -0.25, -0.549999999999983, -0.200000000000017, -0.349999999999994, -0.0999999999999943, -0.150000000000006, -0.75, -0.400000000000006, -0.5, -0.299999999999983, -0.400000000000006, -0.400000000000006, -0.25, -0.199999999999989, -0.450000000000017, -0.349999999999994, -0.449999999999989, -0.300000000000011, -0.150000000000006, -0.349999999999994, -0.5, -0.5, -0.550000000000011, -0.149999999999977, -1.5, -0.350000000000023, -0.199999999999989, -0.25, -0.199999999999989, -0.400000000000006, -0.200000000000017, -0.049999999999983, -0.400000000000006, -0.349999999999994, -0.550000000000011, -0.650000000000006, -0.299999999999983, -0.5, -0.0500000000000114, -0.150000000000006, 0.150000000000006, -0.0999999999999943, -0.0500000000000114, 0.150000000000006), DIVE_SURF = c("dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21", "dive21"), X = c(2050L, 2062L, 2026L, 2078L, 2058L, 2076L, 2050L, 2068L, 2060L, 2078L, 2058L, 2088L, 2080L, 2065L, 2088L, 2076L, 2084L, 2105L, 2084L, 2102L, 2123L, 2096L, 2074L, 2054L, 2090L, 2089L, 2080L, 2078L, 2068L, 2092L, 2084L, 2082L, 2094L, 2056L, 2062L, 2067L, 2082L, 2084L, 2091L, 2058L, 2076L, 2098L, 2104L, 2090L, 2058L, 2050L, 2080L, 2074L, 2074L, 2082L, 2070L, 2088L, 2062L, 2062L, 2082L, 2086L, 2070L, 2081L, 2092L, 2058L, 2060L, 2076L, 2094L, 2083L, 2072L, 2107L, 2104L, 2066L, 2110L, 2104L, 2072L, 2076L, 2065L, 2042L, 2066L, 2093L, 2080L, 2083L, 2108L, 2107L, 2086L, 2096L, 2126L ), Y = c(2036L, 2000L, 2049L, 1966L, 2042L, 2078L, 2072L, 2055L, 2036L, 2128L, 2044L, 2112L, 2066L, 2051L, 2102L, 2060L, 2054L, 2043L, 2034L, 2086L, 1980L, 2076L, 2003L, 2033L, 2107L, 1992L, 2028L, 2027L, 2024L, 2005L, 2050L, 2010L, 1944L, 2010L, 2046L, 2020L, 2088L, 2086L, 2034L, 2066L, 2060L, 2152L, 2044L, 2078L, 2040L, 2067L, 2080L, 2072L, 2073L, 2028L, 2066L, 2082L, 2030L, 2042L, 1990L, 2076L, 2054L, 2064L, 2016L, 2048L, 2029L, 2008L, 2090L, 2038L, 2026L, 2096L, 2002L, 2025L, 2001L, 2098L, 2061L, 2022L, 2054L, 2064L, 2043L, 2090L, 2042L, 2086L, 2073L, 2066L, 2040L, 2081L, 2087L), Z = c(2488L, 2484L, 2490L, 2486L, 2488L, 2492L, 2498L, 2490L, 2492L, 2484L, 2491L, 2494L, 2497L, 2493L, 2488L, 2493L, 2494L, 2484L, 2486L, 2487L, 2478L, 2490L, 2478L, 2493L, 2490L, 2486L, 2488L, 2486L, 2488L, 2482L, 2488L, 2480L, 2480L, 2488L, 2490L, 2490L, 2490L, 2489L, 2492L, 2490L, 2486L, 2480L, 2488L, 2491L, 2486L, 2488L, 2488L, 2494L, 2490L, 2488L, 2492L, 2498L, 2484L, 2491L, 2480L, 2491L, 2497L, 2487L, 2482L, 2490L, 2490L, 2478L, 2488L, 2492L, 2492L, 2482L, 2484L, 2489L, 2482L, 2484L, 2485L, 2492L, 2488L, 2493L, 2487L, 2490L, 2492L, 2488L, 2490L, 2487L, 2484L, 2486L, 2478L)), .Names = c("DEPTH", "Smooth.Vert.Speed", "DIVE_SURF", "X", "Y", "Z"), row.names = 7222:7304, class = "data.frame")
and I am looking to plot DEPTH, X, Y and Z on separate graphs with a common X axis.
-
aaronwolen almost 12 yearsGood call, that probably makes more sense.
-
Jojo almost 12 years@BenBolker Ah this is perfect thankyou. Is there a way with this plot to have every variable a different colour and to name each y-axis differently? You are right, I left out the time variable as its a date-time variable and I havn't figured out how to plot it properly yet using the POSIXct function.
-
Jojo almost 12 yearsI would also like to invert the yaxis for DEPTH if possible?
-
Ben Bolker almost 12 years(1) your best bet for assigning colours and naming the axes is as in @aaronwolen's answer. (2) I think both
lattice
andggplot2
should handle POSIXct axes OK. (3) inverting depth could be tricky: @DirkEddelbuettel's answer will allow you the greatest flexibility. -
Jojo almost 12 years@aaronwolen any suggestions as to how I might handle each plot individually in terms of formatting colour/yaxis labelling etc?
-
Jojo almost 12 yearsThis is excellent however a little complicated for my purposes and am finding it a little difficult to tease apart what would be appropriate for me to use with my example. Which part of the code is specific to "connecting" the plots together vertically and creating a common x-axis? +1 for this brilliant example of data visualisation.
-
Dirk Eddelbuettel almost 12 yearsYes, the code does too much for your purposes as I have all the computing (and data gathering) to do. Look into the final function which uses the excellent
layout()
function, and the calls the individual plots. I have another (simpler) example at home where I set up a regular grid in a similar way and the plot multiple functions; hopefully I'll remember to add this at some point. -
Jojo almost 12 yearsThis code works very nicely aswell. Is there any way to change the colours for each plot and get individual y axis labels for this one?
-
Ben Bolker almost 12 yearschanging colours is very easy (add
colour=variable
as an argument to theaes()
function; see?scale_colour_manual
if you want to assign the colours manually rather than automatically). Individual y-axis labels will be harder, but the strip labels on the right hand side might be an acceptable substitute. I liketheme_update(theme_bw())
and importinglibrary(grid)
and adding+opts(panel.margin=unit(0,"lines"))
to the ggplot call, for aesthetic reasons. As I said above, @DirkEddelbuettel's approach will be most customizable. -
aaronwolen almost 12 yearsI updated the code so each variable would be colored differently. I don't know of a way to add individual labels for each y-axis or invert the y-axis for DEPTH only. The intent of ggplot2's faceting functions are to place subsets of your data in separate panels while still plotting them against the same x & y variables. Hence only one label per axis. Given what you want to do, perhaps it would be best just to generate 4 separate plots stacked on top of each another and only label the bottom plot's x-axis.
-
Jojo almost 12 years@BenBolker Thanks this is very helpful. Just one final thing. Is there a way to change the strip labels on the right hand side?
-
aaronwolen almost 12 yearsThe strip labels come from your data.frame, so renaming there will change the labels in the plot:
dt.df$variable <- factor(dt.df$variable, levels = c("DEPTH", "X", "Y", "Z"), labels = c("depth-var", "x-var", "y-var", "z-var"))
-
Jojo almost 12 yearsYou can input a list of sequential ylim values within the plot function that are applied to each individual plot in order. Ive updated the code in the answer. Thanks for all the Help @BenBolker!
-
Ben Bolker almost 12 yearsit would be OK with me if you accepted your own answer rather than mine, since you've come closer to fully answering your question. Perhaps you could edit your answer to show a picture of the result?
-
Dirk Eddelbuettel over 10 yearsTry this link from my site. The code is nine years old though...
-
Matt over 8 yearsYou can also use
+ facet_wrap(variable ~ ., ncol = 1)
for a variation on this. See docs.ggplot2.org/0.9.3.1/facet_wrap.html.