It is possible to create inset graphs?ggplot put a plot inside of another plot?Embedding a subplot in ggplot (ggsubplot)How can you get ggplot2 to display an inset figure when the main one has a log scale?Combine scatter plot with rotated histogram of residuals in Rggplot2 fix overlapping y-labelsPlot two graphs in same plot in RHow can I handle R CMD check “no visible binding for global variable” notes when my ggplot2 syntax is sensible?How can we make xkcd style graphs?Create a stacked density graph in ggplot2create templates using ggplot2 syntax?data.table vs dplyr: can one do something well the other can't or does poorly?Is it possible to create a line graph in r, where the colour of the line changes at a specific pointIn R, how can I store an inset graph for later arranging it with grid.arrange?inset map using ggplot2

How to illustrate the Mean Value theorem?

Have 1.5% of all nuclear reactors ever built melted down?

What does this symbol on the box of power supply mean?

Should breaking down something like a door be adjudicated as an attempt to beat its AC and HP, or as an ability check against a set DC?

what kind of chord progession is this?

Is the derivative with respect to a fermion field Grassmann-odd?

Did people Unsnap to where they were?

How do I partition a matrx into blocks and replace zeros with dots?

What are these arcade games in Ghostbusters 1984?

C++ forcing function parameter evalution order

Using credit/debit card details vs swiping a card in a payment (credit card) terminal

What is this opening/position called, and what is white’s best move?

Who will lead the country until there is a new Tory leader?

Is the taxi route omitted in low visibility (LVP)?

At what point in European history could a government build a printing press given a basic description?

Make 24 using exactly three 3s

Inconsistent results from Wolfram Could

Any advice on creating fictional locations in real places when writing historical fiction?

Would Jetfuel for a modern jet like an F-16 or a F-35 be producable in the WW2 era?

What is Theresa May waiting for?

My players want to grind XP but we're using milestone advancement

Boss wants me to falsify a report. How should I document this unethical demand?

Grammar Question Regarding "Are the" or "Is the" When Referring to Something that May or May not be Plural

Gladys goes shopping



It is possible to create inset graphs?


ggplot put a plot inside of another plot?Embedding a subplot in ggplot (ggsubplot)How can you get ggplot2 to display an inset figure when the main one has a log scale?Combine scatter plot with rotated histogram of residuals in Rggplot2 fix overlapping y-labelsPlot two graphs in same plot in RHow can I handle R CMD check “no visible binding for global variable” notes when my ggplot2 syntax is sensible?How can we make xkcd style graphs?Create a stacked density graph in ggplot2create templates using ggplot2 syntax?data.table vs dplyr: can one do something well the other can't or does poorly?Is it possible to create a line graph in r, where the colour of the line changes at a specific pointIn R, how can I store an inset graph for later arranging it with grid.arrange?inset map using ggplot2






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








20















I know that when you use par( fig=c( ... ), new=T ), you can create inset graphs. However, I was wondering if it is possible to use ggplot2 library to create 'inset' graphs.



UPDATE 1: I tried using the par() with ggplot2, but it does not work.



UPDATE 2: I found a working solution at ggplot2 GoogleGroups using grid::viewport().










share|improve this question



















  • 1





    This post on the Learning R blog goes over how to plot inside a plot. The blog has a lot of other great posts on ggplot2.

    – Erik Shilts
    Mar 7 '11 at 15:03

















20















I know that when you use par( fig=c( ... ), new=T ), you can create inset graphs. However, I was wondering if it is possible to use ggplot2 library to create 'inset' graphs.



UPDATE 1: I tried using the par() with ggplot2, but it does not work.



UPDATE 2: I found a working solution at ggplot2 GoogleGroups using grid::viewport().










share|improve this question



















  • 1





    This post on the Learning R blog goes over how to plot inside a plot. The blog has a lot of other great posts on ggplot2.

    – Erik Shilts
    Mar 7 '11 at 15:03













20












20








20


15






I know that when you use par( fig=c( ... ), new=T ), you can create inset graphs. However, I was wondering if it is possible to use ggplot2 library to create 'inset' graphs.



UPDATE 1: I tried using the par() with ggplot2, but it does not work.



UPDATE 2: I found a working solution at ggplot2 GoogleGroups using grid::viewport().










share|improve this question
















I know that when you use par( fig=c( ... ), new=T ), you can create inset graphs. However, I was wondering if it is possible to use ggplot2 library to create 'inset' graphs.



UPDATE 1: I tried using the par() with ggplot2, but it does not work.



UPDATE 2: I found a working solution at ggplot2 GoogleGroups using grid::viewport().







r graphics ggplot2 insets






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Aug 19 '16 at 21:00









zx8754

31.6k768108




31.6k768108










asked Mar 7 '11 at 12:21









SamSam

3,020113756




3,020113756







  • 1





    This post on the Learning R blog goes over how to plot inside a plot. The blog has a lot of other great posts on ggplot2.

    – Erik Shilts
    Mar 7 '11 at 15:03












  • 1





    This post on the Learning R blog goes over how to plot inside a plot. The blog has a lot of other great posts on ggplot2.

    – Erik Shilts
    Mar 7 '11 at 15:03







1




1





This post on the Learning R blog goes over how to plot inside a plot. The blog has a lot of other great posts on ggplot2.

– Erik Shilts
Mar 7 '11 at 15:03





This post on the Learning R blog goes over how to plot inside a plot. The blog has a lot of other great posts on ggplot2.

– Erik Shilts
Mar 7 '11 at 15:03












5 Answers
5






active

oldest

votes


















24














Section 8.4 of the book explains how to do this. The trick is to use the grid package's viewports.



#Any old plot
a_plot <- ggplot(cars, aes(speed, dist)) + geom_line()

#A viewport taking up a fraction of the plot area
vp <- viewport(width = 0.4, height = 0.4, x = 0.8, y = 0.2)

#Just draw the plot twice
png("test.png")
print(a_plot)
print(a_plot, vp = vp)
dev.off()





share|improve this answer




















  • 2





    Worth pointing out that, if one wants another plot as the inset, the crucial line is to be print(another_plot, vp = vp). It took me a while to figure out. +1

    – mts
    Apr 9 '17 at 20:44



















13














I prefer solutions that work with ggsave. After a lot of googling around I ended up with this (which is a general formula for positioning and sizing the plot that you insert.



library(tidyverse)

plot1 = qplot(1.00*mpg, 1.00*wt, data=mtcars) # Make sure x and y values are floating values in plot 1
plot2 = qplot(hp, cyl, data=mtcars)
plot(plot1)

# Specify position of plot2 (in percentages of plot1)
# This is in the top left and 25% width and 25% height
xleft = 0.05
xright = 0.30
ybottom = 0.70
ytop = 0.95

# Calculate position in plot1 coordinates
# Extract x and y values from plot1
l1 = ggplot_build(plot1)
x1 = l1$layout$panel_ranges[[1]]$x.range[1]
x2 = l1$layout$panel_ranges[[1]]$x.range[2]
y1 = l1$layout$panel_ranges[[1]]$y.range[1]
y2 = l1$layout$panel_ranges[[1]]$y.range[2]
xdif = x2-x1
ydif = y2-y1
xmin = x1 + (xleft*xdif)
xmax = x1 + (xright*xdif)
ymin = y1 + (ybottom*ydif)
ymax = y1 + (ytop*ydif)

# Get plot2 and make grob
g2 = ggplotGrob(plot2)
plot3 = plot1 + annotation_custom(grob = g2, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
plot(plot3)

ggsave(filename = "test.png", plot = plot3)

# Try and make a weird combination of plots
g1 <- ggplotGrob(plot1)
g2 <- ggplotGrob(plot2)
g3 <- ggplotGrob(plot3)

library(gridExtra)
library(grid)

t1 = arrangeGrob(g1,ncol=1, left = textGrob("A", y = 1, vjust=1, gp=gpar(fontsize=20)))
t2 = arrangeGrob(g2,ncol=1, left = textGrob("B", y = 1, vjust=1, gp=gpar(fontsize=20)))
t3 = arrangeGrob(g3,ncol=1, left = textGrob("C", y = 1, vjust=1, gp=gpar(fontsize=20)))

final = arrangeGrob(t1,t2,t3, layout_matrix = cbind(c(1,2), c(3,3)))
grid.arrange(final)

ggsave(filename = "test2.png", plot = final)


Image showing inset and relatively complex layout






share|improve this answer




















  • 1





    I think they've updated the ggplot package and now, in order to extract the position from the plot1 coordinates the format should be like this: l1$layout$panel_ranges[[1]]$x.range[1]. Note the l1$layout$panel_ranges....

    – s_scolary
    Dec 4 '17 at 21:39











  • You are right. I have updated the answer accordingly.

    – pallevillesen
    Dec 14 '17 at 9:42


















6














Much simpler solution utilizing ggplot2 and egg. Most importantly this solution works with ggsave.



library(tidyverse)
library(egg)
plotx <- ggplot(mpg, aes(displ, hwy)) + geom_point()
plotx +
annotation_custom(
ggplotGrob(plotx),
xmin = 5, xmax = 7, ymin = 30, ymax = 44
)
ggsave(filename = "inset-plot.png")





share|improve this answer




















  • 5





    Hey @stackinator. +1 for concise example and mentioning the egg package. Note that just using library(ggplot2) is more than enough (one does not need the extra tidyverse nor egg)

    – Valentin
    Aug 14 '18 at 19:26


















5














Alternatively, can use the cowplot R package by Claus O. Wilke (cowplot is a powerful extension of ggplot2). The author has an example about plotting an inset inside a larger graph in this intro vignette. Here is some adapted code:



library(cowplot)

main.plot <-
ggplot(data = mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
geom_point(size = 2.5)

inset.plot <- main.plot + theme(legend.position = "none")

plot.with.inset <-
ggdraw() +
draw_plot(main.plot) +
draw_plot(inset.plot, x = 0.07, y = .7, width = .3, height = .3)

# Can save the plot with ggsave()
ggsave(filename = "plot.with.inset.png",
plot = plot.with.inset,
width = 17,
height = 12,
units = "cm",
dpi = 300)


enter image description here






share|improve this answer























  • I think you can also pass main.plot to ggdraw() to save one line of code.

    – crsh
    May 3 at 10:27


















1














'ggplot2' >= 3.0.0 makes possible new approaches for adding insets, as now tibble objects containing lists as member columns can be passed as data. The objects in the list column can be even whole ggplots... The latest version of my package 'ggpmisc' provides geom_plot(), geom_table() and geom_grob(), and also versions that use npc units instead of native data units for locating the insets. These geoms can add multiple insets per call and obey faceting, which annotation_custom() does not. I copy the example from the help page, which adds an inset with a zoom-in detail of the main plot as an inset.



library(tibble)
library(ggpmisc)
p <-
ggplot(data = mtcars, mapping = aes(wt, mpg)) +
geom_point()

df <- tibble(x = 0.01, y = 0.01,
plot = list(p +
coord_cartesian(xlim = c(3, 4),
ylim = c(13, 16)) +
labs(x = NULL, y = NULL) +
theme_bw(10)))
p +
expand_limits(x = 0, y = 0) +
geom_plot_npc(data = df, aes(npcx = x, npcy = y, label = plot))



ggplot with ggplot as inset



Or a barplot as inset, taken from the package vignette.



library(tibble)
library(ggpmisc)
p <- ggplot(mpg, aes(factor(cyl), hwy, fill = factor(cyl))) +
stat_summary(geom = "col", fun.y = mean, width = 2/3) +
labs(x = "Number of cylinders", y = NULL, title = "Means") +
scale_fill_discrete(guide = FALSE)

data.tb <- tibble(x = 7, y = 44,
plot = list(p +
theme_bw(8)))

ggplot(mpg, aes(displ, hwy, colour = factor(cyl))) +
geom_plot(data = data.tb, aes(x, y, label = plot)) +
geom_point() +
labs(x = "Engine displacement (l)", y = "Fuel use efficiency (MPG)",
colour = "Engine cylindersn(number)") +
theme_bw()


enter image description here






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f5219671%2fit-is-possible-to-create-inset-graphs%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    5 Answers
    5






    active

    oldest

    votes








    5 Answers
    5






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    24














    Section 8.4 of the book explains how to do this. The trick is to use the grid package's viewports.



    #Any old plot
    a_plot <- ggplot(cars, aes(speed, dist)) + geom_line()

    #A viewport taking up a fraction of the plot area
    vp <- viewport(width = 0.4, height = 0.4, x = 0.8, y = 0.2)

    #Just draw the plot twice
    png("test.png")
    print(a_plot)
    print(a_plot, vp = vp)
    dev.off()





    share|improve this answer




















    • 2





      Worth pointing out that, if one wants another plot as the inset, the crucial line is to be print(another_plot, vp = vp). It took me a while to figure out. +1

      – mts
      Apr 9 '17 at 20:44
















    24














    Section 8.4 of the book explains how to do this. The trick is to use the grid package's viewports.



    #Any old plot
    a_plot <- ggplot(cars, aes(speed, dist)) + geom_line()

    #A viewport taking up a fraction of the plot area
    vp <- viewport(width = 0.4, height = 0.4, x = 0.8, y = 0.2)

    #Just draw the plot twice
    png("test.png")
    print(a_plot)
    print(a_plot, vp = vp)
    dev.off()





    share|improve this answer




















    • 2





      Worth pointing out that, if one wants another plot as the inset, the crucial line is to be print(another_plot, vp = vp). It took me a while to figure out. +1

      – mts
      Apr 9 '17 at 20:44














    24












    24








    24







    Section 8.4 of the book explains how to do this. The trick is to use the grid package's viewports.



    #Any old plot
    a_plot <- ggplot(cars, aes(speed, dist)) + geom_line()

    #A viewport taking up a fraction of the plot area
    vp <- viewport(width = 0.4, height = 0.4, x = 0.8, y = 0.2)

    #Just draw the plot twice
    png("test.png")
    print(a_plot)
    print(a_plot, vp = vp)
    dev.off()





    share|improve this answer















    Section 8.4 of the book explains how to do this. The trick is to use the grid package's viewports.



    #Any old plot
    a_plot <- ggplot(cars, aes(speed, dist)) + geom_line()

    #A viewport taking up a fraction of the plot area
    vp <- viewport(width = 0.4, height = 0.4, x = 0.8, y = 0.2)

    #Just draw the plot twice
    png("test.png")
    print(a_plot)
    print(a_plot, vp = vp)
    dev.off()






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Mar 24 at 3:47









    Jessica Burnett

    17110




    17110










    answered Mar 7 '11 at 14:06









    Richie CottonRichie Cotton

    82.1k30192313




    82.1k30192313







    • 2





      Worth pointing out that, if one wants another plot as the inset, the crucial line is to be print(another_plot, vp = vp). It took me a while to figure out. +1

      – mts
      Apr 9 '17 at 20:44













    • 2





      Worth pointing out that, if one wants another plot as the inset, the crucial line is to be print(another_plot, vp = vp). It took me a while to figure out. +1

      – mts
      Apr 9 '17 at 20:44








    2




    2





    Worth pointing out that, if one wants another plot as the inset, the crucial line is to be print(another_plot, vp = vp). It took me a while to figure out. +1

    – mts
    Apr 9 '17 at 20:44






    Worth pointing out that, if one wants another plot as the inset, the crucial line is to be print(another_plot, vp = vp). It took me a while to figure out. +1

    – mts
    Apr 9 '17 at 20:44














    13














    I prefer solutions that work with ggsave. After a lot of googling around I ended up with this (which is a general formula for positioning and sizing the plot that you insert.



    library(tidyverse)

    plot1 = qplot(1.00*mpg, 1.00*wt, data=mtcars) # Make sure x and y values are floating values in plot 1
    plot2 = qplot(hp, cyl, data=mtcars)
    plot(plot1)

    # Specify position of plot2 (in percentages of plot1)
    # This is in the top left and 25% width and 25% height
    xleft = 0.05
    xright = 0.30
    ybottom = 0.70
    ytop = 0.95

    # Calculate position in plot1 coordinates
    # Extract x and y values from plot1
    l1 = ggplot_build(plot1)
    x1 = l1$layout$panel_ranges[[1]]$x.range[1]
    x2 = l1$layout$panel_ranges[[1]]$x.range[2]
    y1 = l1$layout$panel_ranges[[1]]$y.range[1]
    y2 = l1$layout$panel_ranges[[1]]$y.range[2]
    xdif = x2-x1
    ydif = y2-y1
    xmin = x1 + (xleft*xdif)
    xmax = x1 + (xright*xdif)
    ymin = y1 + (ybottom*ydif)
    ymax = y1 + (ytop*ydif)

    # Get plot2 and make grob
    g2 = ggplotGrob(plot2)
    plot3 = plot1 + annotation_custom(grob = g2, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
    plot(plot3)

    ggsave(filename = "test.png", plot = plot3)

    # Try and make a weird combination of plots
    g1 <- ggplotGrob(plot1)
    g2 <- ggplotGrob(plot2)
    g3 <- ggplotGrob(plot3)

    library(gridExtra)
    library(grid)

    t1 = arrangeGrob(g1,ncol=1, left = textGrob("A", y = 1, vjust=1, gp=gpar(fontsize=20)))
    t2 = arrangeGrob(g2,ncol=1, left = textGrob("B", y = 1, vjust=1, gp=gpar(fontsize=20)))
    t3 = arrangeGrob(g3,ncol=1, left = textGrob("C", y = 1, vjust=1, gp=gpar(fontsize=20)))

    final = arrangeGrob(t1,t2,t3, layout_matrix = cbind(c(1,2), c(3,3)))
    grid.arrange(final)

    ggsave(filename = "test2.png", plot = final)


    Image showing inset and relatively complex layout






    share|improve this answer




















    • 1





      I think they've updated the ggplot package and now, in order to extract the position from the plot1 coordinates the format should be like this: l1$layout$panel_ranges[[1]]$x.range[1]. Note the l1$layout$panel_ranges....

      – s_scolary
      Dec 4 '17 at 21:39











    • You are right. I have updated the answer accordingly.

      – pallevillesen
      Dec 14 '17 at 9:42















    13














    I prefer solutions that work with ggsave. After a lot of googling around I ended up with this (which is a general formula for positioning and sizing the plot that you insert.



    library(tidyverse)

    plot1 = qplot(1.00*mpg, 1.00*wt, data=mtcars) # Make sure x and y values are floating values in plot 1
    plot2 = qplot(hp, cyl, data=mtcars)
    plot(plot1)

    # Specify position of plot2 (in percentages of plot1)
    # This is in the top left and 25% width and 25% height
    xleft = 0.05
    xright = 0.30
    ybottom = 0.70
    ytop = 0.95

    # Calculate position in plot1 coordinates
    # Extract x and y values from plot1
    l1 = ggplot_build(plot1)
    x1 = l1$layout$panel_ranges[[1]]$x.range[1]
    x2 = l1$layout$panel_ranges[[1]]$x.range[2]
    y1 = l1$layout$panel_ranges[[1]]$y.range[1]
    y2 = l1$layout$panel_ranges[[1]]$y.range[2]
    xdif = x2-x1
    ydif = y2-y1
    xmin = x1 + (xleft*xdif)
    xmax = x1 + (xright*xdif)
    ymin = y1 + (ybottom*ydif)
    ymax = y1 + (ytop*ydif)

    # Get plot2 and make grob
    g2 = ggplotGrob(plot2)
    plot3 = plot1 + annotation_custom(grob = g2, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
    plot(plot3)

    ggsave(filename = "test.png", plot = plot3)

    # Try and make a weird combination of plots
    g1 <- ggplotGrob(plot1)
    g2 <- ggplotGrob(plot2)
    g3 <- ggplotGrob(plot3)

    library(gridExtra)
    library(grid)

    t1 = arrangeGrob(g1,ncol=1, left = textGrob("A", y = 1, vjust=1, gp=gpar(fontsize=20)))
    t2 = arrangeGrob(g2,ncol=1, left = textGrob("B", y = 1, vjust=1, gp=gpar(fontsize=20)))
    t3 = arrangeGrob(g3,ncol=1, left = textGrob("C", y = 1, vjust=1, gp=gpar(fontsize=20)))

    final = arrangeGrob(t1,t2,t3, layout_matrix = cbind(c(1,2), c(3,3)))
    grid.arrange(final)

    ggsave(filename = "test2.png", plot = final)


    Image showing inset and relatively complex layout






    share|improve this answer




















    • 1





      I think they've updated the ggplot package and now, in order to extract the position from the plot1 coordinates the format should be like this: l1$layout$panel_ranges[[1]]$x.range[1]. Note the l1$layout$panel_ranges....

      – s_scolary
      Dec 4 '17 at 21:39











    • You are right. I have updated the answer accordingly.

      – pallevillesen
      Dec 14 '17 at 9:42













    13












    13








    13







    I prefer solutions that work with ggsave. After a lot of googling around I ended up with this (which is a general formula for positioning and sizing the plot that you insert.



    library(tidyverse)

    plot1 = qplot(1.00*mpg, 1.00*wt, data=mtcars) # Make sure x and y values are floating values in plot 1
    plot2 = qplot(hp, cyl, data=mtcars)
    plot(plot1)

    # Specify position of plot2 (in percentages of plot1)
    # This is in the top left and 25% width and 25% height
    xleft = 0.05
    xright = 0.30
    ybottom = 0.70
    ytop = 0.95

    # Calculate position in plot1 coordinates
    # Extract x and y values from plot1
    l1 = ggplot_build(plot1)
    x1 = l1$layout$panel_ranges[[1]]$x.range[1]
    x2 = l1$layout$panel_ranges[[1]]$x.range[2]
    y1 = l1$layout$panel_ranges[[1]]$y.range[1]
    y2 = l1$layout$panel_ranges[[1]]$y.range[2]
    xdif = x2-x1
    ydif = y2-y1
    xmin = x1 + (xleft*xdif)
    xmax = x1 + (xright*xdif)
    ymin = y1 + (ybottom*ydif)
    ymax = y1 + (ytop*ydif)

    # Get plot2 and make grob
    g2 = ggplotGrob(plot2)
    plot3 = plot1 + annotation_custom(grob = g2, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
    plot(plot3)

    ggsave(filename = "test.png", plot = plot3)

    # Try and make a weird combination of plots
    g1 <- ggplotGrob(plot1)
    g2 <- ggplotGrob(plot2)
    g3 <- ggplotGrob(plot3)

    library(gridExtra)
    library(grid)

    t1 = arrangeGrob(g1,ncol=1, left = textGrob("A", y = 1, vjust=1, gp=gpar(fontsize=20)))
    t2 = arrangeGrob(g2,ncol=1, left = textGrob("B", y = 1, vjust=1, gp=gpar(fontsize=20)))
    t3 = arrangeGrob(g3,ncol=1, left = textGrob("C", y = 1, vjust=1, gp=gpar(fontsize=20)))

    final = arrangeGrob(t1,t2,t3, layout_matrix = cbind(c(1,2), c(3,3)))
    grid.arrange(final)

    ggsave(filename = "test2.png", plot = final)


    Image showing inset and relatively complex layout






    share|improve this answer















    I prefer solutions that work with ggsave. After a lot of googling around I ended up with this (which is a general formula for positioning and sizing the plot that you insert.



    library(tidyverse)

    plot1 = qplot(1.00*mpg, 1.00*wt, data=mtcars) # Make sure x and y values are floating values in plot 1
    plot2 = qplot(hp, cyl, data=mtcars)
    plot(plot1)

    # Specify position of plot2 (in percentages of plot1)
    # This is in the top left and 25% width and 25% height
    xleft = 0.05
    xright = 0.30
    ybottom = 0.70
    ytop = 0.95

    # Calculate position in plot1 coordinates
    # Extract x and y values from plot1
    l1 = ggplot_build(plot1)
    x1 = l1$layout$panel_ranges[[1]]$x.range[1]
    x2 = l1$layout$panel_ranges[[1]]$x.range[2]
    y1 = l1$layout$panel_ranges[[1]]$y.range[1]
    y2 = l1$layout$panel_ranges[[1]]$y.range[2]
    xdif = x2-x1
    ydif = y2-y1
    xmin = x1 + (xleft*xdif)
    xmax = x1 + (xright*xdif)
    ymin = y1 + (ybottom*ydif)
    ymax = y1 + (ytop*ydif)

    # Get plot2 and make grob
    g2 = ggplotGrob(plot2)
    plot3 = plot1 + annotation_custom(grob = g2, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
    plot(plot3)

    ggsave(filename = "test.png", plot = plot3)

    # Try and make a weird combination of plots
    g1 <- ggplotGrob(plot1)
    g2 <- ggplotGrob(plot2)
    g3 <- ggplotGrob(plot3)

    library(gridExtra)
    library(grid)

    t1 = arrangeGrob(g1,ncol=1, left = textGrob("A", y = 1, vjust=1, gp=gpar(fontsize=20)))
    t2 = arrangeGrob(g2,ncol=1, left = textGrob("B", y = 1, vjust=1, gp=gpar(fontsize=20)))
    t3 = arrangeGrob(g3,ncol=1, left = textGrob("C", y = 1, vjust=1, gp=gpar(fontsize=20)))

    final = arrangeGrob(t1,t2,t3, layout_matrix = cbind(c(1,2), c(3,3)))
    grid.arrange(final)

    ggsave(filename = "test2.png", plot = final)


    Image showing inset and relatively complex layout







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Dec 14 '17 at 9:43

























    answered Jun 16 '16 at 11:15









    pallevillesenpallevillesen

    505313




    505313







    • 1





      I think they've updated the ggplot package and now, in order to extract the position from the plot1 coordinates the format should be like this: l1$layout$panel_ranges[[1]]$x.range[1]. Note the l1$layout$panel_ranges....

      – s_scolary
      Dec 4 '17 at 21:39











    • You are right. I have updated the answer accordingly.

      – pallevillesen
      Dec 14 '17 at 9:42












    • 1





      I think they've updated the ggplot package and now, in order to extract the position from the plot1 coordinates the format should be like this: l1$layout$panel_ranges[[1]]$x.range[1]. Note the l1$layout$panel_ranges....

      – s_scolary
      Dec 4 '17 at 21:39











    • You are right. I have updated the answer accordingly.

      – pallevillesen
      Dec 14 '17 at 9:42







    1




    1





    I think they've updated the ggplot package and now, in order to extract the position from the plot1 coordinates the format should be like this: l1$layout$panel_ranges[[1]]$x.range[1]. Note the l1$layout$panel_ranges....

    – s_scolary
    Dec 4 '17 at 21:39





    I think they've updated the ggplot package and now, in order to extract the position from the plot1 coordinates the format should be like this: l1$layout$panel_ranges[[1]]$x.range[1]. Note the l1$layout$panel_ranges....

    – s_scolary
    Dec 4 '17 at 21:39













    You are right. I have updated the answer accordingly.

    – pallevillesen
    Dec 14 '17 at 9:42





    You are right. I have updated the answer accordingly.

    – pallevillesen
    Dec 14 '17 at 9:42











    6














    Much simpler solution utilizing ggplot2 and egg. Most importantly this solution works with ggsave.



    library(tidyverse)
    library(egg)
    plotx <- ggplot(mpg, aes(displ, hwy)) + geom_point()
    plotx +
    annotation_custom(
    ggplotGrob(plotx),
    xmin = 5, xmax = 7, ymin = 30, ymax = 44
    )
    ggsave(filename = "inset-plot.png")





    share|improve this answer




















    • 5





      Hey @stackinator. +1 for concise example and mentioning the egg package. Note that just using library(ggplot2) is more than enough (one does not need the extra tidyverse nor egg)

      – Valentin
      Aug 14 '18 at 19:26















    6














    Much simpler solution utilizing ggplot2 and egg. Most importantly this solution works with ggsave.



    library(tidyverse)
    library(egg)
    plotx <- ggplot(mpg, aes(displ, hwy)) + geom_point()
    plotx +
    annotation_custom(
    ggplotGrob(plotx),
    xmin = 5, xmax = 7, ymin = 30, ymax = 44
    )
    ggsave(filename = "inset-plot.png")





    share|improve this answer




















    • 5





      Hey @stackinator. +1 for concise example and mentioning the egg package. Note that just using library(ggplot2) is more than enough (one does not need the extra tidyverse nor egg)

      – Valentin
      Aug 14 '18 at 19:26













    6












    6








    6







    Much simpler solution utilizing ggplot2 and egg. Most importantly this solution works with ggsave.



    library(tidyverse)
    library(egg)
    plotx <- ggplot(mpg, aes(displ, hwy)) + geom_point()
    plotx +
    annotation_custom(
    ggplotGrob(plotx),
    xmin = 5, xmax = 7, ymin = 30, ymax = 44
    )
    ggsave(filename = "inset-plot.png")





    share|improve this answer















    Much simpler solution utilizing ggplot2 and egg. Most importantly this solution works with ggsave.



    library(tidyverse)
    library(egg)
    plotx <- ggplot(mpg, aes(displ, hwy)) + geom_point()
    plotx +
    annotation_custom(
    ggplotGrob(plotx),
    xmin = 5, xmax = 7, ymin = 30, ymax = 44
    )
    ggsave(filename = "inset-plot.png")






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Sep 11 '18 at 11:20

























    answered Jun 15 '18 at 13:30









    stackinatorstackinator

    1,3641825




    1,3641825







    • 5





      Hey @stackinator. +1 for concise example and mentioning the egg package. Note that just using library(ggplot2) is more than enough (one does not need the extra tidyverse nor egg)

      – Valentin
      Aug 14 '18 at 19:26












    • 5





      Hey @stackinator. +1 for concise example and mentioning the egg package. Note that just using library(ggplot2) is more than enough (one does not need the extra tidyverse nor egg)

      – Valentin
      Aug 14 '18 at 19:26







    5




    5





    Hey @stackinator. +1 for concise example and mentioning the egg package. Note that just using library(ggplot2) is more than enough (one does not need the extra tidyverse nor egg)

    – Valentin
    Aug 14 '18 at 19:26





    Hey @stackinator. +1 for concise example and mentioning the egg package. Note that just using library(ggplot2) is more than enough (one does not need the extra tidyverse nor egg)

    – Valentin
    Aug 14 '18 at 19:26











    5














    Alternatively, can use the cowplot R package by Claus O. Wilke (cowplot is a powerful extension of ggplot2). The author has an example about plotting an inset inside a larger graph in this intro vignette. Here is some adapted code:



    library(cowplot)

    main.plot <-
    ggplot(data = mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
    geom_point(size = 2.5)

    inset.plot <- main.plot + theme(legend.position = "none")

    plot.with.inset <-
    ggdraw() +
    draw_plot(main.plot) +
    draw_plot(inset.plot, x = 0.07, y = .7, width = .3, height = .3)

    # Can save the plot with ggsave()
    ggsave(filename = "plot.with.inset.png",
    plot = plot.with.inset,
    width = 17,
    height = 12,
    units = "cm",
    dpi = 300)


    enter image description here






    share|improve this answer























    • I think you can also pass main.plot to ggdraw() to save one line of code.

      – crsh
      May 3 at 10:27















    5














    Alternatively, can use the cowplot R package by Claus O. Wilke (cowplot is a powerful extension of ggplot2). The author has an example about plotting an inset inside a larger graph in this intro vignette. Here is some adapted code:



    library(cowplot)

    main.plot <-
    ggplot(data = mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
    geom_point(size = 2.5)

    inset.plot <- main.plot + theme(legend.position = "none")

    plot.with.inset <-
    ggdraw() +
    draw_plot(main.plot) +
    draw_plot(inset.plot, x = 0.07, y = .7, width = .3, height = .3)

    # Can save the plot with ggsave()
    ggsave(filename = "plot.with.inset.png",
    plot = plot.with.inset,
    width = 17,
    height = 12,
    units = "cm",
    dpi = 300)


    enter image description here






    share|improve this answer























    • I think you can also pass main.plot to ggdraw() to save one line of code.

      – crsh
      May 3 at 10:27













    5












    5








    5







    Alternatively, can use the cowplot R package by Claus O. Wilke (cowplot is a powerful extension of ggplot2). The author has an example about plotting an inset inside a larger graph in this intro vignette. Here is some adapted code:



    library(cowplot)

    main.plot <-
    ggplot(data = mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
    geom_point(size = 2.5)

    inset.plot <- main.plot + theme(legend.position = "none")

    plot.with.inset <-
    ggdraw() +
    draw_plot(main.plot) +
    draw_plot(inset.plot, x = 0.07, y = .7, width = .3, height = .3)

    # Can save the plot with ggsave()
    ggsave(filename = "plot.with.inset.png",
    plot = plot.with.inset,
    width = 17,
    height = 12,
    units = "cm",
    dpi = 300)


    enter image description here






    share|improve this answer













    Alternatively, can use the cowplot R package by Claus O. Wilke (cowplot is a powerful extension of ggplot2). The author has an example about plotting an inset inside a larger graph in this intro vignette. Here is some adapted code:



    library(cowplot)

    main.plot <-
    ggplot(data = mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
    geom_point(size = 2.5)

    inset.plot <- main.plot + theme(legend.position = "none")

    plot.with.inset <-
    ggdraw() +
    draw_plot(main.plot) +
    draw_plot(inset.plot, x = 0.07, y = .7, width = .3, height = .3)

    # Can save the plot with ggsave()
    ggsave(filename = "plot.with.inset.png",
    plot = plot.with.inset,
    width = 17,
    height = 12,
    units = "cm",
    dpi = 300)


    enter image description here







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Oct 16 '18 at 18:21









    ValentinValentin

    2,4491732




    2,4491732












    • I think you can also pass main.plot to ggdraw() to save one line of code.

      – crsh
      May 3 at 10:27

















    • I think you can also pass main.plot to ggdraw() to save one line of code.

      – crsh
      May 3 at 10:27
















    I think you can also pass main.plot to ggdraw() to save one line of code.

    – crsh
    May 3 at 10:27





    I think you can also pass main.plot to ggdraw() to save one line of code.

    – crsh
    May 3 at 10:27











    1














    'ggplot2' >= 3.0.0 makes possible new approaches for adding insets, as now tibble objects containing lists as member columns can be passed as data. The objects in the list column can be even whole ggplots... The latest version of my package 'ggpmisc' provides geom_plot(), geom_table() and geom_grob(), and also versions that use npc units instead of native data units for locating the insets. These geoms can add multiple insets per call and obey faceting, which annotation_custom() does not. I copy the example from the help page, which adds an inset with a zoom-in detail of the main plot as an inset.



    library(tibble)
    library(ggpmisc)
    p <-
    ggplot(data = mtcars, mapping = aes(wt, mpg)) +
    geom_point()

    df <- tibble(x = 0.01, y = 0.01,
    plot = list(p +
    coord_cartesian(xlim = c(3, 4),
    ylim = c(13, 16)) +
    labs(x = NULL, y = NULL) +
    theme_bw(10)))
    p +
    expand_limits(x = 0, y = 0) +
    geom_plot_npc(data = df, aes(npcx = x, npcy = y, label = plot))



    ggplot with ggplot as inset



    Or a barplot as inset, taken from the package vignette.



    library(tibble)
    library(ggpmisc)
    p <- ggplot(mpg, aes(factor(cyl), hwy, fill = factor(cyl))) +
    stat_summary(geom = "col", fun.y = mean, width = 2/3) +
    labs(x = "Number of cylinders", y = NULL, title = "Means") +
    scale_fill_discrete(guide = FALSE)

    data.tb <- tibble(x = 7, y = 44,
    plot = list(p +
    theme_bw(8)))

    ggplot(mpg, aes(displ, hwy, colour = factor(cyl))) +
    geom_plot(data = data.tb, aes(x, y, label = plot)) +
    geom_point() +
    labs(x = "Engine displacement (l)", y = "Fuel use efficiency (MPG)",
    colour = "Engine cylindersn(number)") +
    theme_bw()


    enter image description here






    share|improve this answer



























      1














      'ggplot2' >= 3.0.0 makes possible new approaches for adding insets, as now tibble objects containing lists as member columns can be passed as data. The objects in the list column can be even whole ggplots... The latest version of my package 'ggpmisc' provides geom_plot(), geom_table() and geom_grob(), and also versions that use npc units instead of native data units for locating the insets. These geoms can add multiple insets per call and obey faceting, which annotation_custom() does not. I copy the example from the help page, which adds an inset with a zoom-in detail of the main plot as an inset.



      library(tibble)
      library(ggpmisc)
      p <-
      ggplot(data = mtcars, mapping = aes(wt, mpg)) +
      geom_point()

      df <- tibble(x = 0.01, y = 0.01,
      plot = list(p +
      coord_cartesian(xlim = c(3, 4),
      ylim = c(13, 16)) +
      labs(x = NULL, y = NULL) +
      theme_bw(10)))
      p +
      expand_limits(x = 0, y = 0) +
      geom_plot_npc(data = df, aes(npcx = x, npcy = y, label = plot))



      ggplot with ggplot as inset



      Or a barplot as inset, taken from the package vignette.



      library(tibble)
      library(ggpmisc)
      p <- ggplot(mpg, aes(factor(cyl), hwy, fill = factor(cyl))) +
      stat_summary(geom = "col", fun.y = mean, width = 2/3) +
      labs(x = "Number of cylinders", y = NULL, title = "Means") +
      scale_fill_discrete(guide = FALSE)

      data.tb <- tibble(x = 7, y = 44,
      plot = list(p +
      theme_bw(8)))

      ggplot(mpg, aes(displ, hwy, colour = factor(cyl))) +
      geom_plot(data = data.tb, aes(x, y, label = plot)) +
      geom_point() +
      labs(x = "Engine displacement (l)", y = "Fuel use efficiency (MPG)",
      colour = "Engine cylindersn(number)") +
      theme_bw()


      enter image description here






      share|improve this answer

























        1












        1








        1







        'ggplot2' >= 3.0.0 makes possible new approaches for adding insets, as now tibble objects containing lists as member columns can be passed as data. The objects in the list column can be even whole ggplots... The latest version of my package 'ggpmisc' provides geom_plot(), geom_table() and geom_grob(), and also versions that use npc units instead of native data units for locating the insets. These geoms can add multiple insets per call and obey faceting, which annotation_custom() does not. I copy the example from the help page, which adds an inset with a zoom-in detail of the main plot as an inset.



        library(tibble)
        library(ggpmisc)
        p <-
        ggplot(data = mtcars, mapping = aes(wt, mpg)) +
        geom_point()

        df <- tibble(x = 0.01, y = 0.01,
        plot = list(p +
        coord_cartesian(xlim = c(3, 4),
        ylim = c(13, 16)) +
        labs(x = NULL, y = NULL) +
        theme_bw(10)))
        p +
        expand_limits(x = 0, y = 0) +
        geom_plot_npc(data = df, aes(npcx = x, npcy = y, label = plot))



        ggplot with ggplot as inset



        Or a barplot as inset, taken from the package vignette.



        library(tibble)
        library(ggpmisc)
        p <- ggplot(mpg, aes(factor(cyl), hwy, fill = factor(cyl))) +
        stat_summary(geom = "col", fun.y = mean, width = 2/3) +
        labs(x = "Number of cylinders", y = NULL, title = "Means") +
        scale_fill_discrete(guide = FALSE)

        data.tb <- tibble(x = 7, y = 44,
        plot = list(p +
        theme_bw(8)))

        ggplot(mpg, aes(displ, hwy, colour = factor(cyl))) +
        geom_plot(data = data.tb, aes(x, y, label = plot)) +
        geom_point() +
        labs(x = "Engine displacement (l)", y = "Fuel use efficiency (MPG)",
        colour = "Engine cylindersn(number)") +
        theme_bw()


        enter image description here






        share|improve this answer













        'ggplot2' >= 3.0.0 makes possible new approaches for adding insets, as now tibble objects containing lists as member columns can be passed as data. The objects in the list column can be even whole ggplots... The latest version of my package 'ggpmisc' provides geom_plot(), geom_table() and geom_grob(), and also versions that use npc units instead of native data units for locating the insets. These geoms can add multiple insets per call and obey faceting, which annotation_custom() does not. I copy the example from the help page, which adds an inset with a zoom-in detail of the main plot as an inset.



        library(tibble)
        library(ggpmisc)
        p <-
        ggplot(data = mtcars, mapping = aes(wt, mpg)) +
        geom_point()

        df <- tibble(x = 0.01, y = 0.01,
        plot = list(p +
        coord_cartesian(xlim = c(3, 4),
        ylim = c(13, 16)) +
        labs(x = NULL, y = NULL) +
        theme_bw(10)))
        p +
        expand_limits(x = 0, y = 0) +
        geom_plot_npc(data = df, aes(npcx = x, npcy = y, label = plot))



        ggplot with ggplot as inset



        Or a barplot as inset, taken from the package vignette.



        library(tibble)
        library(ggpmisc)
        p <- ggplot(mpg, aes(factor(cyl), hwy, fill = factor(cyl))) +
        stat_summary(geom = "col", fun.y = mean, width = 2/3) +
        labs(x = "Number of cylinders", y = NULL, title = "Means") +
        scale_fill_discrete(guide = FALSE)

        data.tb <- tibble(x = 7, y = 44,
        plot = list(p +
        theme_bw(8)))

        ggplot(mpg, aes(displ, hwy, colour = factor(cyl))) +
        geom_plot(data = data.tb, aes(x, y, label = plot)) +
        geom_point() +
        labs(x = "Engine displacement (l)", y = "Fuel use efficiency (MPG)",
        colour = "Engine cylindersn(number)") +
        theme_bw()


        enter image description here







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Apr 11 at 14:45









        Pedro AphaloPedro Aphalo

        1,6311114




        1,6311114



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f5219671%2fit-is-possible-to-create-inset-graphs%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

            Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

            Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript