motivation

library(tidyverse, quietly=TRUE)
library(grid)

define my_theme

my_theme <- function(){
  list(  
    theme_classic(base_size=10) +
      theme(line = element_line(size = 0.25),
            axis.ticks.length=unit(-1, "mm"),
            axis.text.x = element_text(margin=unit(c(1,1,1,1), "mm")),
            axis.text.y = element_text(margin=unit(c(1,1,1,1), "mm")),
            legend.position = "none",
            strip.background = element_blank()
      ))
}

prepare data and ggplot

d <- tibble(t=1:100, 
            y=sin(seq(0, 10*pi, length.out=100)) + rnorm(100, 0, 0.5),
            y_sys=sin(seq(0, 10*pi, length.out=100)))

g1 <- ggplot(d) + 
  geom_point(aes(t, y), pch=1) +
  geom_line(aes(t, y_sys), alpha=0.5) +
  geom_line(aes(t, y_sys), lty=3)

g1

modify plot using my_theme

g2 <- g1 + my_theme()
g2

compare the two plots

my_subplot <- function(nrow=3, ncol=1, 
                       height=7, width=7,
                       ggs) {
  # height and width are in unit inch
  # ggs: ggplot objects wrapped as list
  # order of ggs is like matrix(1:length(ggs), nrow, ncol)
  # todo: spanning
  my_layout <- grid.layout(nrow, ncol,
                           heights=unit(rep(height, nrow)/nrow, 
                                        rep("inch", nrow)),
                           widths=unit(rep(width, ncol)/ncol, 
                                       rep("inch", ncol)))
  
  fg <- frameGrob(my_layout)
  n <- length(ggs)
  for (i in 1:n) {
    my_row <- ifelse(i %% nrow == 0, nrow, i %% nrow)
    my_col <- ifelse(i %% nrow == 0, i %/% nrow, (i %/% nrow) + 1)
    fg <- placeGrob(fg, 
                    ggplotGrob(ggs[[i]]),
                    row=my_row, col=my_col)
  }
  fg
}

c.f. https://rpubs.com/katzkagaya/851632

grid.newpage()
grid.draw(
  my_subplot(
    2, 1,
    3.5, 5,
    ggs=list(g1, g2)
  )
)

references

LS0tCnRpdGxlOiAiY2hhbmdlIG9mIGF4aXMgc3R5bGUiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMgbW90aXZhdGlvbgotIGNoYW5nZSB0aGUgZGVmYXVsdCBnZ3Bsb3Qgc3R5bGUgaW50byBhIHN0eWxlIGNsb3NlIHRvIHB1YmxpY2F0aW9uIHJlYWR5CgoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlLCBxdWlldGx5PVRSVUUpCmxpYnJhcnkoZ3JpZCkKYGBgCgoKIyBkZWZpbmUgbXlfdGhlbWUKYGBge3J9Cm15X3RoZW1lIDwtIGZ1bmN0aW9uKCl7CiAgbGlzdCggIAogICAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemU9MTApICsKICAgICAgdGhlbWUobGluZSA9IGVsZW1lbnRfbGluZShzaXplID0gMC4yNSksCiAgICAgICAgICAgIGF4aXMudGlja3MubGVuZ3RoPXVuaXQoLTEsICJtbSIpLAogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChtYXJnaW49dW5pdChjKDEsMSwxLDEpLCAibW0iKSksCiAgICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KG1hcmdpbj11bml0KGMoMSwxLDEsMSksICJtbSIpKSwKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpCiAgICAgICkpCn0KYGBgCgoKIyBwcmVwYXJlIGRhdGEgYW5kIGdncGxvdApgYGB7cn0KZCA8LSB0aWJibGUodD0xOjEwMCwgCiAgICAgICAgICAgIHk9c2luKHNlcSgwLCAxMCpwaSwgbGVuZ3RoLm91dD0xMDApKSArIHJub3JtKDEwMCwgMCwgMC41KSwKICAgICAgICAgICAgeV9zeXM9c2luKHNlcSgwLCAxMCpwaSwgbGVuZ3RoLm91dD0xMDApKSkKCmcxIDwtIGdncGxvdChkKSArIAogIGdlb21fcG9pbnQoYWVzKHQsIHkpLCBwY2g9MSkgKwogIGdlb21fbGluZShhZXModCwgeV9zeXMpLCBhbHBoYT0wLjUpICsKICBnZW9tX2xpbmUoYWVzKHQsIHlfc3lzKSwgbHR5PTMpCgpnMQpgYGAKCiMgbW9kaWZ5IHBsb3QgdXNpbmcgbXlfdGhlbWUKYGBge3J9CmcyIDwtIGcxICsgbXlfdGhlbWUoKQpnMgpgYGAKCiMgY29tcGFyZSB0aGUgdHdvIHBsb3RzCgpgYGB7cn0KbXlfc3VicGxvdCA8LSBmdW5jdGlvbihucm93PTMsIG5jb2w9MSwgCiAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0PTcsIHdpZHRoPTcsCiAgICAgICAgICAgICAgICAgICAgICAgZ2dzKSB7CiAgIyBoZWlnaHQgYW5kIHdpZHRoIGFyZSBpbiB1bml0IGluY2gKICAjIGdnczogZ2dwbG90IG9iamVjdHMgd3JhcHBlZCBhcyBsaXN0CiAgIyBvcmRlciBvZiBnZ3MgaXMgbGlrZSBtYXRyaXgoMTpsZW5ndGgoZ2dzKSwgbnJvdywgbmNvbCkKICAjIHRvZG86IHNwYW5uaW5nCiAgbXlfbGF5b3V0IDwtIGdyaWQubGF5b3V0KG5yb3csIG5jb2wsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodHM9dW5pdChyZXAoaGVpZ2h0LCBucm93KS9ucm93LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiaW5jaCIsIG5yb3cpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGhzPXVuaXQocmVwKHdpZHRoLCBuY29sKS9uY29sLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJpbmNoIiwgbmNvbCkpKQogIAogIGZnIDwtIGZyYW1lR3JvYihteV9sYXlvdXQpCiAgbiA8LSBsZW5ndGgoZ2dzKQogIGZvciAoaSBpbiAxOm4pIHsKICAgIG15X3JvdyA8LSBpZmVsc2UoaSAlJSBucm93ID09IDAsIG5yb3csIGkgJSUgbnJvdykKICAgIG15X2NvbCA8LSBpZmVsc2UoaSAlJSBucm93ID09IDAsIGkgJS8lIG5yb3csIChpICUvJSBucm93KSArIDEpCiAgICBmZyA8LSBwbGFjZUdyb2IoZmcsIAogICAgICAgICAgICAgICAgICAgIGdncGxvdEdyb2IoZ2dzW1tpXV0pLAogICAgICAgICAgICAgICAgICAgIHJvdz1teV9yb3csIGNvbD1teV9jb2wpCiAgfQogIGZnCn0KYGBgCmMuZi4gaHR0cHM6Ly9ycHVicy5jb20va2F0emthZ2F5YS84NTE2MzIKCmBgYHtyfQpncmlkLm5ld3BhZ2UoKQpncmlkLmRyYXcoCiAgbXlfc3VicGxvdCgKICAgIDIsIDEsCiAgICAzLjUsIDUsCiAgICBnZ3M9bGlzdChnMSwgZzIpCiAgKQopCmBgYAoKIyByZWZlcmVuY2VzCi0gTXVycmVsbCwgUC4gKDIwMDUpLiBSIGdyYXBoaWNzLiBDaGFwbWFuIGFuZCBIYWxsL0NSQy4KLSBNdXJyZWxsLCBQLiAoMjAwOSkuIFIgZ3JhcGhpY3MuIFdpbGV5IEludGVyZGlzY2lwbGluYXJ5IFJldmlld3M6IENvbXB1dGF0aW9uYWwgU3RhdGlzdGljcywgMSgyKSwgMjE2LTIyMC4KLSBXaWNraGFtLCBILiwgJiBHcm9sZW11bmQsIEcuICgyMDE2KS4gUiBmb3IgZGF0YSBzY2llbmNlOiBpbXBvcnQsIHRpZHksIHRyYW5zZm9ybSwgdmlzdWFsaXplLCBhbmQgbW9kZWwgZGF0YS4gIiBPJ1JlaWxseSBNZWRpYSwgSW5jLiIuCg==