ggplot2:顺序添加层的重新调整因子

ggplot2: Releveling factors for sequentially added layers

我正在为 class "foo" 编写绘图方法。我希望此绘图函数获取多个 foo 对象并将它们绘制在同一张图上。

代码

#parabola function
parabolas <- function(x, parm) {
  y <- parm[1]*(x^2)+parm[2]*x+parm[3]
  return(y)
}
#make foo object
make_foo <- function(a, b, c) {
   x <- runif(100, 0 , 20)
   y <- parabolas(x = x, parm = c(a,b,c)) + rnorm(100, mean = 100 ,sd = 100)
   foo <- list(data = data.frame(x = x, y = y), parameters = c(a,b,c))
   class(foo) <- "foo"
   return(foo)
}


#plot function
plot.foo <- function(x, 
                 ...,
                 labels) {

 a <- ggplot(NULL, aes(x = x, y = y))

 foo.list <- list(x, ...)
 #browser()
 #build plot
 for(i in 1:length(foo.list)){
   foo.obj <- foo.list[[i]]
   foo.obj$data$lab <- factor(rep(labels[i], nrow(foo.obj$data)), levels = labels)
a <- a + geom_point(data = foo.obj$data, size = 5, alpha = .7, aes(color = lab))
a <- a + stat_function(data = foo.obj$data,
                       fun = parabolas, 
                       args = list(parm = foo.obj$parameters), size = 1.2)
 }
 return(a)
}

问题

ggplot 将根据因子标签的字母顺序重新调整 lab 的因子水平。在顺序添加这些层时,我不知道如何选择 lab 的因子水平顺序。我希望 labels 的第一个元素对应于绘制的第一个 foo 对象,第二个元素对应于第二个 foo 对象,依此类推。

foo1 <- make_foo(2, 10, 3)
foo2 <- make_foo(-6, -3, 2000)
plot(foo1, foo2, labels = c("obj1","obj2"))
#label for foo1 is "obj1" and label for foo2 is "obj2"
plot(foo1, foo2, labels = c("obj3","obj2"))
#label for foo1 should be "obj3" and label for foo2 should be "obj2"

动机

我之所以这样构建绘图函数,而不是将数据框绑定在一起并将正确的因子水平分配给 lab,是因为在那种特定情况下,facet_wrapstat_function 不能很好地协同工作。应用多个 stat_function 并一起使用 facet_wrap 后,所有曲线将出现在每个面板中。此线程说明了类似的 problem。 因为我将这些不同的图层限制为不同的数据集,facet_wrap 将根据用于绘制它的 data/parameters 正确地刻面每个 stat_function 图。

plot(foo1, foo2, labels = c("z","a")) + facet_wrap(~lab, scales = "free")
#Shows facet_wrap works as intended but the labels for foo1 and foo2 are
#still not in the intended order

您可以通过设置 limits 手动覆盖色阶的顺序。方法如下:

plot.foo <- function(x, 
                     ...,
                     labels) {

  a <- ggplot(NULL, aes(x = x, y = y))

  foo.list <- list(x, ...)
  #browser()
  #build plot
  for(i in 1:length(foo.list)){
    foo.obj <- foo.list[[i]]
    foo.obj$data$lab <- factor(rep(labels[i], nrow(foo.obj$data)), levels = labels)
    a <- a + geom_point(data = foo.obj$data, size = 5, alpha = .7, aes(color = lab))
    a <- a + stat_function(data = foo.obj$data,
                           fun = parabolas, 
                           args = list(parm = foo.obj$parameters), size = 1.2)
  }

  ### added line:
  a <- a + scale_color_discrete(limits = labels)
  ###

  return(a)
}