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

R: 相对于绘图边界而不是绘图上的固定位置放置geom_text()

  •  3
  • cparmstrong  · 技术社区  · 7 年前

    我正在使用 ggplot2

    在每个图上,我需要放置两条表示某些策略实现的截止线(旁边有一个单词),以便阅读这些图的人可以轻松识别实现前后的性能差异。下面是我目前使用的大致代码。

    gg_plot1<- ggplot(data=ggdata, aes(x=Year, y=measure1, group=Area, color=Area)) +
      geom_vline(xintercept=2011, color="#EE0000") +
      geom_text(aes(x=2011, label="City1\n", y=0.855), color="#EE0000", angle=90, hjust=0, family="serif") +
      geom_vline(xintercept=2007, color="#000099") +
      geom_text(aes(x=2007, label="City2", y=0.855), color="#000099", angle=0, hjust=1, family="serif") +
      geom_line(size=.75) +
      geom_point(size=1.5) +
      scale_y_continuous(breaks=round(seq(min(ggdata$measure1, na.rm=T), max(ggdata$measure1, na.rm=T), by=0.01), 2)) +
      scale_x_continuous(breaks=min(ggdata$Year):max(ggdata$Year)) +
      scale_color_manual(values=c("#EE0000", "#00DDFF", "#009900", "#000099")) +
      theme(axis.text.x = element_text(angle=90, vjust=1),
            panel.background = element_rect(fill="white", color="white"),
            panel.grid.major = element_line(color="grey95"),
            text = element_text(size=11, family="serif"))
    

    这种实现的问题在于,它依赖于将两者放置在一起 geom_text() 在特定图形的特定位置。这些不同的度量值都有不同的范围,所以为了做到这一点,我需要逐点进行,并找到一个放置它们的位置。我更喜欢做的是把每个图的范围缩小X%,然后把 geom_text()

    有没有办法做我想做的事?如果非要我猜的话,这有点像使用相对定位而不是绝对定位,但我还没有找到在ggplot中实现这一点的方法。作为记录,我知道这两个 geom_text()

    提要:另一种可视化方法是在截止年份将线从实线改为虚线。这可能吗?我不确定客户是否会想要,但如果有人能告诉我在哪里学习如何做到这一点,我愿意将其作为一种选择。

    编辑以添加:

    示例数据显示了在不同y范围下运行时发生的情况

    ggdata <- data.frame(Area=rep(c("City1", "City2", "City3", "City4"), times=7),
                         Year=c(rep(2006,4), rep(2007,4), rep(2008,4), rep(2009,4), rep(2010,4), rep(2011,4), rep(2012,4)),
                         measure1=rnorm(28,10,2),
                         measure2=rnorm(28,50,10))
    

    具有 s在适当位置,但这是使用上面的代码在绘图内的固定位置完成的。当我使用具有不同y范围的不同度量来复制代码时,它最终会拉伸绘图窗口。 Sample plot

    1 回复  |  直到 7 年前
        1
  •  3
  •   eipi10    7 年前

    可以使用数据的y范围定位到文本标签。我在下面的例子中明确地设置了y限制,但这并不是绝对必要的,除非您想更改默认值。还可以使用数据的x范围调整文本标签的x位置。无论数据的y范围如何,下面的代码都会将标签定位在绘图的底部。

    geom_text annotate . geom_文本 多次过度打印文本标签,数据中每行一次。 注释 打印一次标签。

    ypos = min(ggdata$measure1) + 0.005*diff(range(ggdata$measure1))
    xv = 0.02
    xh = 0.01
    xadj = diff(range(ggdata$Year))
    
    ggplot(data=ggdata, aes(x=Year, y=measure1, group=Area, color=Area)) +
      geom_vline(xintercept=2011, color="#EE0000") +
      geom_vline(xintercept=2007, color="#000099") +
      geom_line(size=.75) +
      geom_point(size=1.5) +
      annotate(geom="text", x=2011 - xv*xadj, label="City1", y=ypos, color="#EE0000", angle=90, hjust=0, family="serif") +
      annotate(geom="text", x=2007 - xh*xadj, label="City2", y=ypos, color="#000099", angle=0, hjust=1, family="serif") +
      scale_y_continuous(limits=range(ggdata$measure1),
                         breaks=round(seq(min(ggdata$measure1, na.rm=T), max(ggdata$measure1, na.rm=T), by=1), 0)) +
      scale_x_continuous(breaks=min(ggdata$Year):max(ggdata$Year)) +
      scale_color_manual(values=c("#EE0000", "#00DDFF", "#009900", "#000099")) +
      theme(axis.text.x = element_text(angle=90, vjust=1),
            panel.background = element_rect(fill="white", color="white"),
            panel.grid.major = element_line(color="grey95"),
            text = element_text(size=11, family="serif"))
    

    enter image description here

    更新:

    首先,我们用三个测量柱创建可再现的数据:

    library(ggplot2)
    library(gridExtra)
    library(scales)
    
    set.seed(4)
    ggdata <- data.frame(Year=rep(2006:2012,each=4),
                         Area=rep(paste0("City",1:4), 7),
                         measure1=rnorm(28,10,2),
                         measure2=rnorm(28,50,10),
                         measure3=rnorm(28,-50,5))
    

    现在,我们从上面获取代码并将其打包到函数中。函数接受一个名为 measure_var aes_string 而不是 aes 在…内 ggplot .

    plot_func = function(measure_var) {
    
      ypos = min(ggdata[ , measure_var]) + 0.005*diff(range(ggdata[ , measure_var]))
      xv = 0.02
      xh = 0.01
      xadj = diff(range(ggdata$Year))
    
      ggplot(data=ggdata, aes_string(x="Year", y=measure_var, group="Area", color="Area")) +
        geom_vline(xintercept=2011, color="#EE0000") +
        geom_vline(xintercept=2007, color="#000099") +
        geom_line(size=.75) +
        geom_point(size=1.5) +
        annotate(geom="text", x=2011 - xv*xadj, label="City1", y=ypos, 
                 color="#EE0000", angle=90, hjust=0, family="serif") +
        annotate(geom="text", x=2007 - xh*xadj, label="City2", y=ypos, 
                 color="#000099", angle=0, hjust=1, family="serif") +
        scale_y_continuous(limits=range(ggdata[ , measure_var]),
                           breaks=pretty_breaks(5)) +
        scale_x_continuous(breaks=min(ggdata$Year):max(ggdata$Year)) +
        scale_color_manual(values=c("#EE0000", "#00DDFF", "#009900", "#000099")) +
        theme(axis.text.x = element_text(angle=90, vjust=1),
              panel.background = element_rect(fill="white", color="white"),
              panel.grid.major = element_line(color="grey95"),
              text = element_text(size=11, family="serif")) +
        ggtitle(paste("Plot of", measure_var))
    }
    

    我们现在可以这样运行函数一次: plot_func("measure1") . 但是,让我们使用 lapply . 我们给予 拉普拉 具有度量列名称的向量( names(ggdata)[grepl("measure", names(ggdata))] plot_func 依次在每个列上,将生成的图存储在列表中 plot_list .

    plot_list = lapply(names(ggdata)[grepl("measure", names(ggdata))], plot_func)
    

    现在,如果我们愿意,我们可以使用 grid.arrange

    # Function to get legend from a ggplot as a separate graphical object
    # Source: https://github.com/tidyverse/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs/047381b48b0f0ef51a174286a595817f01a0dfad
    g_legend<-function(a.gplot){
      tmp <- ggplot_gtable(ggplot_build(a.gplot))
      leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
      legend <- tmp$grobs[[leg]]
      return(legend)
    }
    
    # Get legend
    leg = g_legend(plot_list[[1]])
    
    # Lay out all of the plots together with a single legend
    grid.arrange(arrangeGrob(grobs=lapply(plot_list, function(x) x + guides(colour=FALSE))),
                 leg,
                 ncol=2, widths=c(10,1))
    

    enter image description here