0

I would like to have a main panel with a smaller panel about 1/6 of the height of the main underneath. This is the typical setup to show price history plus some technical indicators (such as MACD) in stock charts. I am not sure if the MACD will show below, if not then click on indicators and add MACD

TSLA with MACD

enter image description here

Stephen
  • 550
  • 1
  • 4
  • 15
  • No MACD doesn't show, better post a screenshot of what you expect to see. Also, what have you tried, the post is very broad/unclear. Please provide example input, expected output, what have you tried so far? – zx8754 Nov 16 '18 at 14:51
  • I can use par(mfrow=c(3,1) but the panels are equal size. – Stephen Nov 16 '18 at 15:15
  • 1
    So if the question is "how to align 3 plots on xaxis" then this is a possible duplicate of https://stackoverflow.com/questions/13294952/left-align-two-graph-edges-ggplot – zx8754 Nov 16 '18 at 15:19
  • 1
    It's easier to help you if you include a simple [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input and desired output that can be used to test and verify possible solutions. `layout()` might be a good alternative to `par()` because it has options for heights. But without knowing exactly what your plotting commands look like it's hard to say for sure. – MrFlick Nov 16 '18 at 16:17
  • it can be any two lines: – Stephen Nov 16 '18 at 18:01
  • it can be any two lines: `a <- arima.sim(n = 100, list(ar = c(0.9)) , sd = sqrt(0.2)) b <- arima.sim(n = 100, list(ar = c(0.6, -0.48)), sd = sqrt(0.1)) ` the important part is the bottom chart is about 1/6 of the height of the top – Stephen Nov 16 '18 at 18:10

1 Answers1

1

This is absolutely a job for layout. Note that its companion par(mfrow=...) (and mfcol) are effectively (if not actually) using the same mechanisms as layout, but layout allows for different plot order and dimensions between "facets" of the plot.

Some random data:

set.seed(2)
n <- 1e4
somedat <- data.frame(x = seq_len(n), y = cumsum(rnorm(1e4)))
somedat$ydot <- smooth(c(0, diff(somedat$y)))
plot(y~x, data=somedat)

layout works on a matrix, where "0" elements are dead-space (unused), numbered spaces must start from 1 and increment by 1, but these numbers can occupy more than one cell (as long as they are neighboring and rectangular). For example:

m <- matrix(c(1, 0,
              1, 3,
              2, 3), byrow = TRUE, nrow = 3)
heights <- c(4, 1, 1)
widths <- c(3, 1)
layout(m, widths=widths, heights=heights)
layout.show(n=3) # only during dev, it "consumes" the plot so should not be used in production

That last command is only during design of the layout, and it plots out a frame for each numbered area. It should show something like this:

layout frame

(The right border of 3 appears to be cropped here ... that must be an artifact of my copy/paste into SO's plots/imgur thing. It's there.)

Once we call the first layout command, each plot fills the current portion of this plot. When using layout, it's common to need to control par(mar=...) tightly, partially for aesthetics, partly for avoidance of errors. You'll know the latter when you plot and it complains about figure margins too large, in which case change your ratios or increase the overall plot size of the window.

Another thing to control are axes. That is, if two plots stacked top and bottom share the same x-axis (or are intended to imply that), then you need to control the axes to make sure they are on the intended scales. It's academic in this example, but I include it for completeness.

xlim <- range(somedat$x) # little redundant here, but mostly for good practice
layout(m, widths=widths, heights=heights)
# plot 1
par(mar = c(0.1, 4, 4, 2) + 0.1)
plot(y ~ x, data = somedat, type = "l",
     main = "Plot title",
     xlim = xlim, axes = FALSE, frame.plot = TRUE)
axis(2)
# plot 2
par(mar = c(2, 4, 0.1, 2) + 0.1)
plot(ydot ~ x, data = somedat, type = "p", 
     pch = 16, cex = 0.2, xlim = xlim, ann = FALSE)
# plot 3
plot(NA, xlim = 0:1, ylim = 0:1, ann = FALSE)
text(0.5, 0.5, "hello world!")

layout example plot

Each plot area re-uses the par(mar=) of the previous plot area, as can be seen where plot 3 has the same shortened area below the plot (side 1).


To show some more brute-force multi-part plots, this can go beyond sane:

m <- matrix(
  c(1, 1, 1, 1, 7,
    1, 1, 1, 1, 7,
    1, 1, 1, 1, 0,
    1, 1, 1, 1, 4,
    5, 5, 5, 2, 3,
    5, 5, 5, 6, 6),
  byrow = TRUE, nrow = 6)
layout(m)
layout.show(n=7)

(again with that right-border ...)

insane layout demo

r2evans
  • 141,215
  • 6
  • 77
  • 149