代码之家  ›  专栏  ›  技术社区  ›  aaaaa

ggplot2-如何为带有网格的多个绘图添加唯一的图例。排列?

  •  4
  • aaaaa  · 技术社区  · 6 年前

    我有一个内部有4个面板的绘图,用 ggplot2和 grid.arrange>制作。每个面板都有一个相同的图例。

    如何删除4个图例并在绘图的底部创建唯一的图例?

    这里是我的示例数据和绘图:

    set.seed(100)
    df_1=data.frame(lat=rnorm(20),
    lon=RNORM(20)
    cor=c(rep(‘正’,7),rep(‘负’,13)),
    符号=C(rep(99,5),rep(95,6),rep(90,9)))
    
    lst_df=列表(df_1,df_1,df_1,df_1)
    
    
    图书馆(ggplot2)
    库(GridExtra)
    图书馆(网格)
    
    对于(i in 1:长度(lst_df))。{
    p[[i]]=ggplot()。+
    
    几何点(数据=lst_df[[i]]、aes(x=lon,y=lat,大小=sign,颜色=cor),alpha=0.5)+
    
    缩放颜色手册(值=C(“蓝色”、“橙色”),
    名字=“COL”,
    labels=c(“neg”,“pos”),
    指南=指南图例(override.aes=列表(alpha=1,size=3))。+
    
    刻度尺尺寸(范围=C(1,3)
    断裂=C(90、95、99)
    标签=C(1、5、10)
    Name=“test”,
    指南=指南图例(override.aes=列表(colour='black',
    α= 1)
    }
    
    
    网格。排列(P[[1]],P[[2]],P[[3]],P[[4]],
    NCOL=2,nROW=2,
    top=textgrob(表达式(粗体(“test”)),gp=gpar(fontsize=25,face='bold'))
    < /代码> 
    
    

    有什么建议吗? 谢谢<他们当中。

    如何删除4个图例并在底部情节的?

    这里是我的示例数据和绘图:

    set.seed(100)
    df_1 = data.frame(lat = rnorm(20), 
                      lon = rnorm(20), 
                      cor = c(rep('positive', 7), rep('negative', 13)), 
                      sign = c(rep(99, 5), rep(95, 6), rep(90,9)))
    
    lst_df = list(df_1, df_1, df_1, df_1)
    
    
    library(ggplot2)
    library(gridExtra)
    library(grid)
    
    for (i in 1:length(lst_df)) {
    p[[i]] = ggplot() +
    
        geom_point(data=lst_df[[i]], aes(x=lon, y=lat, size=sign, colour = cor), alpha = 0.5) +
    
        scale_color_manual(values=c("blue", "orange"),
                           name='col', 
                           labels = c('neg', 'pos'),
                           guide = guide_legend(override.aes = list(alpha = 1, size = 3))) +
    
        scale_size(range = c(1,3), 
                   breaks = c(90, 95, 99),
                   labels = c(1, 5, 10),
                   name = 'test',
                   guide = guide_legend(override.aes = list(colour = 'black', 
                                                            alpha = 1)))
    }
    
    
    grid.arrange(p[[1]], p[[2]], p[[3]], p[[4]], 
                 ncol=2, nrow=2,
                 top=textGrob(expression(bold("test")), gp=gpar(fontsize=25, face= 'bold')))
    

    enter image description here

    有什么建议吗? 谢谢

    2 回复  |  直到 6 年前
        1
  •  5
  •   camille    6 年前

    这是一个带有 cowplot>code>的工作流,它提供了一些用于将grobs放在一起和提取元素(如图例)的整洁功能。他们有一个 detailed vignette on creating grids of plots with shared legenders like you're looking for.类似地,vignette on plot annotations over cowplot functions for creating and adding labels--they functions much like the other plot elements and can be used in cowplot::plot_grid.>

    这个过程基本上是

    1. 使用 lapply(可能是循环)创建没有图例的绘图列表
    2. 提取一个传说——不管是哪一个,因为它们都是一样的——它被设置在底部
    3. 为标题创建文本注释
    4. 从无图例绘图列表创建网格
    5. 从标题、无图例绘图网格和图例创建网格

    除此之外,加载 cowplot let i t set its default ggplot theme,which I don't special like,so I use cowplot::function notation instead of library(cowplot).

    您可以调整用于生成最终网格的相对高度——这是第一个适合我的比率。

    如果出现这种情况,我几个月前发布了一个关于制作 draw_label grob take theme guidelines的问题,正如您在normal ggplot中所期望的那样;elements like titles;answers from the package author and my specialty function are here

    library(ggplot2)
    …
    
    p_no_Legend<-lapply(p,函数(x)x+主题(Legend.position=“none”))
    Legend<-CowPlot::get_Legend(P[[1]]+主题(Legend.position=“bottom”))
    
    标题<-CowPlot::ggDraw()+CowPlot::Draw_Label(“测试”,fontface=“bold”)
    
    P撊grid<-Cowplot::Plot撊grid(PlotList=P撊no撊legend,ncol=2)
    cowplot::绘图网格(标题,P网格,图例,ncol=1,rel_高度=c(0.1,1,0.2))
    < /代码> 
    
    

    由reprex package(v0.2.0)于2018-09-11创建。

    它提供了一些简洁的功能,可以将grob放在一起并提取诸如图例之类的元素。他们有一个detailed vignette创建具有您所寻找的共享图例的绘图网格。同样,小插曲plot annotations过去考古图用于创建和添加标签的函数——它们的功能与其他绘图元素非常相似,可用于cowplot::plot_grid.

    这个过程基本上是

    1. 创建没有图例的绘图列表,使用lapply(可以是循环)
    2. 提取一个传说——不管是哪一个,因为它们都是一样的——它被设置在底部
    3. 为标题创建文本注释
    4. 从无图例绘图列表创建网格
    5. 从标题、无图例绘图网格和图例创建网格

    作为旁白,装载考古图让它设置默认值ggplot主题,我不太喜欢,所以我用cowplot::function符号而不是library(cowplot).

    您可以调整用于生成最终网格的相对高度——这是第一个适合我的比率。

    如果出现这种情况,几个月前我就提出了一个问题draw_labelGrob采用您通常期望的主题指导原则格格图标题等元素;来自包作者和我的专业功能的答案是here.

    library(ggplot2)
    ...
    
    p_no_legend <- lapply(p, function(x) x + theme(legend.position = "none"))
    legend <- cowplot::get_legend(p[[1]] + theme(legend.position = "bottom"))
    
    title <- cowplot::ggdraw() + cowplot::draw_label("test", fontface = "bold")
    
    p_grid <- cowplot::plot_grid(plotlist = p_no_legend, ncol = 2)
    cowplot::plot_grid(title, p_grid, legend, ncol = 1, rel_heights = c(0.1, 1, 0.2))
    

    创建于2018-09-11reprex package(v0.2.0)。

        2
  •  2
  •   Anonymous coward    6 年前

    正如卡米尔指出的那样, cowplot has a really easy way to do this.您也可以通过手动排列 grobs来完成此操作。如果您有不同宽度、比例和分隔符的绘图,这尤其有效。 one example here.

    手动执行此操作的好处是,除非 cowplot can,否则您可以指定哪些绘图具有X轴标签和Y轴标题/标签,因此在最后,您只能在底部网格上具有X轴标题/标签,而在左侧网格上具有Y轴标题/标签。缺点是,如果有多个绘图,定义多个绘图函数会很麻烦。

    df_plots<-laplly(lst_df,function(x))。{
    GGPROTH()+
    几何点(数据=lst_df[[i]]、aes(x=lon,y=lat,大小=sign,颜色=cor),alpha=0.5)+
    缩放颜色手册(值=C(“蓝色”、“橙色”),
    名字=“COL”,
    labels=c(“neg”,“pos”),
    指南=指南图例(override.aes=列表(alpha=1,size=3))。+
    刻度尺尺寸(范围=C(1,3)
    断裂=C(90、95、99)
    标签=C(1、5、10)
    Name=“test”,
    指南=指南图例(override.aes=列表(colour='black',
    α= 1)
    })
    
    df诳leg<-get诳legend(df诳plots[[1]])诳get legend
    
    df ou plots ou noleg<-lapply(lst ou df,函数(x)制作没有图例的绘图,但是您希望这样做
    GGPROTH()+
    
    几何点(数据=lst_df[[i]]、aes(x=lon,y=lat,大小=sign,颜色=cor),alpha=0.5)+
    
    缩放颜色手册(值=C(“蓝色”、“橙色”),
    名字=“COL”,
    labels=c(“neg”,“pos”),
    指南=指南图例(override.aes=列表(alpha=1,size=3))。+
    主题(legend.position=“none”)
    })
    < /代码> 
    
    

    如果有宽度开始变化的绘图,对齐轴很重要。因为在这个例子中,它们都是相同的,所以这并不重要。

    maxwidth_df_plots<-grid::unit.pmax(df_plots_noleg1$widths[2:5],df_plots_noleg2$widths[2:5],df_plots_noleg3$widths[2:5],df_plots_noleg4$widths[2:5])获取您的grob widths
    
    #df_plots noleg1$widths[2:5]<-as.list(maxwidth1page1)
    #df_plots noleg2$widths[2:5]<-as.list(maxwidth1page1)
    #df_plots noleg3$widths[2:5]<-as.list(maxwidth1page1)
    #df_plots noleg4$widths[2:5]<-as.list(maxwidth1page1)
    
    df ou plots1<-ggplotgrob(df ou plots ou noleg[[1]])
    df ou plots2<-ggplotgrob(df ou plots ou noleg[[2]])
    图3<-ggplotgrob(图3)
    图4<-ggplotgrob(图4)
    
    df_plot_arranged<-网格。排列(arrangegrob(df_plots1,df_plots2,df_plots3,df_plots4,nrow=2)
    arrangegrob(nullgrob(),df_leg,nullgrob(),nrow=1),ncol=1,heights=c(4,0.5),
    top=textgrob(“此处为标题文本框”,gp=gpar(fotsize=12,font=2)))
    < /代码> 
    
    

    我提到的好处是,您可以控制哪些图得到了什么标签。这就是控制宽度的地方,正如您在图像中看到的,右图比左图宽,上图比下图高。

    df ou plots1<-df ou plots noleg[[1]]+theme(axis.title.x=element ou blank(),axis.text.x=element ou blank())
    
    df ou plots2<-df ou plots ou noleg[[2]]+主题(axis.title.x=element ou blank(),axis.title.y=element ou blank(),
    axis.text.x=element_blank(),axis.text.y=element_blank())
    
    df ou plots4<-df ou plots ou noleg[[4]]+主题(axis.title.y=element ou blank(),axis.text.y=element ou blank())
    
    df ou plots1<-ggplotrob(df ou plots1)
    df ou plots2<-ggplotgrob(df ou plots2)
    图3<-ggplotgrob(图3)
    df ou plots4<-ggplotgrob(df ou plots4)
    
    df_plot_arranged<-网格。排列(arrangegrob(df_plots1,df_plots2,df_plots3,df_plots4,nrow=2)
    arrangegrob(nullgrob(),df_leg,nullgrob(),nrow=1),ncol=1,heights=c(4,0.5),
    top=textgrob(“此处为标题文本框”,gp=gpar(fotsize=12,font=2)))
    < /代码> 
    
    

    grobs. 如果您有不同宽度、比例和分隔符的绘图,这尤其有效。One example here.

    手动操作的好处,除非考古图可以,也就是说,可以指定哪些绘图具有X轴标签和Y轴标题/标签,因此在最后,底部网格上只能有X轴标题/标签,而左侧网格上只能有Y轴标题/标签。缺点是,如果有多个绘图,定义多个绘图函数会很麻烦。

    df_plots <- lapply(lst_df, function(x) {
    ggplot() +    
    geom_point(data=lst_df[[i]], aes(x=lon, y=lat, size=sign, colour = cor), alpha = 0.5) +
    scale_color_manual(values=c("blue", "orange"),
                       name='col', 
                       labels = c('neg', 'pos'),
                       guide = guide_legend(override.aes = list(alpha = 1, size = 3))) +
    scale_size(range = c(1,3), 
               breaks = c(90, 95, 99),
               labels = c(1, 5, 10),
               name = 'test',
               guide = guide_legend(override.aes = list(colour = 'black', 
                                                        alpha = 1)))
    })
    
    df_leg <-  get_legend(df_plots[[1]]) # get legend
    
    df_plots_noleg <- lapply(lst_df, function(x) { # make plots with no legends, however you want to do this
    ggplot() +
    
    geom_point(data=lst_df[[i]], aes(x=lon, y=lat, size=sign, colour = cor), alpha = 0.5) +
    
    scale_color_manual(values=c("blue", "orange"),
                       name='col', 
                       labels = c('neg', 'pos'),
                       guide = guide_legend(override.aes = list(alpha = 1, size = 3))) +
    theme(legend.position = "none")
    })
    

    如果有宽度开始变化的绘图,对齐轴很重要。因为在这个例子中它们都是一样的,所以这并不重要。

    #maxWidth_df_plots <- grid::unit.pmax(df_plots_noleg1$widths[2:5], df_plots_noleg2$widths[2:5], df_plots_noleg3$widths[2:5], df_plots_noleg4$widths[2:5]) #get your grob widths
    
    #df_plots_noleg1$widths[2:5] <- as.list(maxWidth1Page1)
    #df_plots_noleg2$widths[2:5] <- as.list(maxWidth1Page1)
    #df_plots_noleg3$widths[2:5] <- as.list(maxWidth1Page1)
    #df_plots_noleg4$widths[2:5] <- as.list(maxWidth1Page1)
    
    df_plots1 <- ggplotGrob(df_plots_noleg[[1]])
    df_plots2 <- ggplotGrob(df_plots_noleg[[2]])
    df_plots3 <- ggplotGrob(df_plots_noleg[[3]])
    df_plots4 <- ggplotGrob(df_plots_noleg[[4]])
    
    df_plot_arranged <- grid.arrange(arrangeGrob(df_plots1, df_plots2, df_plots3, df_plots4, nrow = 2),
                                 arrangeGrob(nullGrob(), df_leg, nullGrob(), nrow = 1), ncol = 1, heights = c(4,0.5),
                                 top = textGrob("Title Text Holder Here", gp = gpar(fotsize = 12, font = 2)))
    

    我提到的好处是,您可以控制哪些图得到了什么标签。这就是控制宽度的地方,正如你在图片中看到的,右边的图比左边宽,上面的图比下面的图高。

    df_plots1 <- df_plots_noleg[[1]] + theme(axis.title.x = element_blank(), axis.text.x = element_blank())
    
    df_plots2 <- df_plots_noleg[[2]] + theme(axis.title.x = element_blank(), axis.title.y = element_blank(),
                                   axis.text.x = element_blank(), axis.text.y = element_blank())
    
    df_plots4 <- df_plots_noleg[[4]] + theme(axis.title.y = element_blank(), axis.text.y = element_blank())
    
    df_plots1 <- ggplotGrob(df_plots1)
    df_plots2 <- ggplotGrob(df_plots2)
    df_plots3 <- ggplotGrob(df_plots_noleg[[3]])
    df_plots4 <- ggplotGrob(df_plots4)
    
    df_plot_arranged <- grid.arrange(arrangeGrob(df_plots1, df_plots2, df_plots3, df_plots4, nrow = 2),
                                 arrangeGrob(nullGrob(), df_leg, nullGrob(), nrow = 1), ncol = 1, heights = c(4,0.5),
                                 top = textGrob("Title Text Holder Here", gp = gpar(fotsize = 12, font = 2)))