1

I have a two-panel lattice lineplot. I want to use the directlabels package to automatically label the lines in each plot. But I want to use a different positioning method for each plot. Specifically, I want to use the first.bumpup method for the first panel, and the last.bumpup method for the second panel. Here is a minimal example:

library(directlabels)
library(lattice)
myDF <- data.frame(
  y     = rep(1:4,         2),
  x     = rep(rep(1:2, 2), 2),
  group = rep(c('a', 'b'), each = 2),
  panel = rep(1:2,         each = 4))
myPlot <- xyplot(y ~ x | panel, groups = group, data = myDF, type = 'l')
direct.label(
  p      = myPlot,
  method = 'first.bumpup')

This code produces a plot in which labels appear on the left-hand side of each panel:

figure produced by example code

I want labels on the left-hand side of the left-hand panel (as in this example), but on the right-hand side of the right-hand panel. What is the simplest way to produce that sort of figure?

I've checked the advanced examples in the directlabels documentation, and they make me think that it may be possible to use different methods for different panels by creating a custom positioning method or a custom panel. But I cannot quite see how to do it.

4

2 回答 2

2

我对此有所ggplot2了解(只是因为我知道ggplot2的比我知道的要多得多lattice)。让我知道你的想法。以下是两种方法。第一个实际上不使用directlabels. 放置规则比较简单,所以我只是用于geom_text标签放置。第二种方法确实使用directlabels,但更复杂。

使用放置标签geom_text

library(dplyr)   # For chaining operator (%>%)
library(ggplot2)
library(cowplot) # For cowplot theme

ggplot(myDF, aes(x, y, colour=group)) + 
  geom_line() +
  geom_text(data=myDF %>% group_by(panel) %>%
              filter(ifelse(panel==1, x==min(x), x==max(x))),
            aes(x + 0.07*(panel-mean(panel)), y, label=group)) +
  facet_grid(~panel) +
  scale_x_continuous(breaks=seq(1,2,0.2)) +
  theme_cowplot() +
  guides(colour=FALSE)

在上面的代码中,geom_text我们只保留x第一个面板的x最小值和第二个面板的最大值,然后将group标签放置在y与这些值配对的x值上。这x + 0.07*(panel-mean(panel))只是将标签稍微远离线条的末端。

在此处输入图像描述

mapply使用和放置标签directlabels

这是一个更复杂的方法,使用directlabels. 我的方法是使用 分别绘制每个“方面” mapply,这样我就可以directlabels对每个面板使用不同的方法,然后将两个图放在一起,就好像它们是同一整体图的两个方面一样。如果你喜欢这个结果,lattice如果 ggplot2 版本都不能满足你的需要,也许你可以把它改编成一个情节。

library(directlabels)
library(ggplot2)
library(gridExtra)
library(cowplot)

pl = mapply(function(pnl, m) {

  # Create plot for each level of panel
  p = ggplot(myDF[myDF$panel==pnl, ], aes(x, y, colour=group)) + 
    geom_line() +
    facet_grid(~panel) +
    scale_x_continuous(breaks=seq(1,2,0.2)) +
    theme_cowplot()

  # # Tweak margins of panel 1
  # if(pnl==1) p = p + theme(plot.margin=unit(rep(0,4),"lines"))

  # Remove y-axis title, labels and ticks for panel 2 and tweak margins
  if(pnl==2) p = p + theme(axis.title.y=element_blank(), 
                           axis.text.y=element_blank(),
                           axis.ticks.y=element_blank())

  # Add directlabels with different method for each panel
  direct.label(p, method=m)
  }, 
  pnl=unique(myDF$panel), m=c("first.bumpup", "last.bumpup"), SIMPLIFY=FALSE)

因为我删除了面板 2 中的 y 轴标题、标签和刻度,所以该面板比面板 1 宽。plot_grid有一个align参数允许我们对齐两个图,使它们具有相同的宽度,但我不知道一种摆脱地块之间空间的方法。grid.arrange还将布置该图,但我们必须手动调整宽度(您也可以手动调整宽度plot_grid)。

# Lay out each panel using plot_grid from cowplot package
plot_grid(plotlist=pl, ncol=2, align="v")

在此处输入图像描述

# Lay out each panel using grid.arrange from gridExtra package
grid.arrange(grobs=pl, ncol=2, widths=c(10,9))

在此处输入图像描述

于 2016-12-14T06:22:23.167 回答
1

这是对 eipi10 的第二个解决方案的改编,它在格子图中创建了所需的效果:

library(directlabels)
library(gridExtra)
library(lattice)

myDF <- data.frame(
  y     = rep(1:4,         2),
  x     = rep(rep(1:2, 2), 2),
  group = rep(c('a', 'b'), each = 2),
  panel = rep(1:2,         each = 4))

plotFunction <- function(panelNumber, labelMethod) {
  myPlot = xyplot(
    y ~ x, 
    groups = group, 
    data   = myDF[myDF$panel==panelNumber, ], 
    type   = 'l')
  direct.label(
    p      = myPlot,
    method = labelMethod)  
} 

panelList = mapply(
  FUN         = plotFunction, 
  panelNumber = unique(myDF$panel), 
  labelMethod = c('first.bumpup', 'last.bumpup'), 
  SIMPLIFY    = FALSE)

grid.arrange(grobs = panelList, ncol = 2)
于 2016-12-17T18:23:48.570 回答