【问题标题】:extending ggplot to take lists and make them available to custom geoms扩展 ggplot 以获取列表并使它们可用于自定义几何
【发布时间】:2019-04-29 19:07:32
【问题描述】:

我正在尝试让 ggplot2 获取列表并使列表中的元素可用于其他自定义几何函数。

我有一个接受列表的新 ggplot 函数:

ggplot.list <- function(data = NULL,
                           mapping = ggplot2::aes(),
                           ...,
                           environment = parent.frame()) {

    p <- ggplot2::ggplot(data=data[[1]],mapping=mapping,..., environment=environment)

    p$data_ext <- data[[2]]
    p
}

我创建了我的列表,并绘制了第一个 data.frame:

l <- list(tibble(x=1:10, y=1:10), tibble(x=1:10+100, y =1:10+200))

ggplot(l) + geom_point(aes(x=x,y=y))

理想情况下,我想创建这样的东西(这不起作用),另一个默认情况下从 ggplot 对象中获取 data_ext 的几何图形

geom_point2 <- function (mapping = NULL, data_ext = NULL, stat = "identity", position = "identity", 
                         ..., na.rm = FALSE, show.legend = NA, inherit.aes = TRUE) 
{
    layer(data_ext = data_ext, mapping = mapping, stat = stat, geom = GeomPoint, 
          position = position, show.legend = show.legend, inherit.aes = inherit.aes, 
          params = list(na.rm = na.rm, ...))
}

ggplot(l) + geom_point(aes(x=x,y=y)) +  geom_point2(aes(x=x,y=y))

我看到我的第二个 data.frame 在 ggplot 对象内,但我不知道如何访问它;也就是说,ggplot(l)$data_ext 有效。 我试过玩 ggproto,但我不够熟练,无法理解如何处理它,以及它是否有帮助。

添加 顺便说一句,我可以用管道实现我想要的,但我不想混淆我的功能的潜在用户:

pipe_point2 <-function (plot, mapping = NULL, data = NULL, stat = "identity", position = "identity", 
                        ..., na.rm = FALSE, show.legend = NA, inherit.aes = TRUE) 
{

  plot +  layer(data = plot$data_ext, mapping = mapping, stat = stat, geom = GeomPoint,
          position = position, show.legend = show.legend, inherit.aes = inherit.aes, 
          params = list(na.rm = na.rm, ...))
}

{ggplot(l) + geom_point(aes(x=x,y=y))} %>%  pipe_point2(aes(x=x,y=y))

【问题讨论】:

    标签: r ggplot2 ggproto


    【解决方案1】:

    我开始制作自己的 ggproto 对象时的重要指示来自以下链接Extending ggplot2。 TL;DR:如果没有 ggproto 对象,编写新的 geom 将变得非常困难。

    我尝试将矩阵走私到自定义 geom_raster() 中,这类似于将列表走私到自定义几何中。我学到的是尺度很难训练,即位置尺度不知道矩阵的限制是什么,填充尺度不知道矩阵的限制是什么。我到了一切看起来都正确的地步,但是彩条指南没有显示正确的数字。

    现在列表可能会更容易一些,因为您可以更轻松地将它们拆分为有意义的元素,并且可以将列表偷运到数据框中。这意味着您可以轻松地做这样的事情并将其提供给 ggplot:

    mydf <- data.frame(x = 1:3, y = 1:3)
    mydf$z <- list(c("A","B"), 1:5, function(x) x/10)
    print(mydf)
    
      x y                   z
    1 1 1                A, B
    2 2 2       1, 2, 3, 4, 5
    3 3 3 function (x) , x/10
    

    而且我认为这将是您将列表走私到 geom 的最佳选择。您只需将其称为函数的额外美学。

    g <- ggplot(mydf) + geom_point(aes(x = x, y = y, z = z))
    # Warning: Ignoring unknown aesthetics: z
    

    并检查该层是否可以访问它:

    layer_data(g)
    
      x y                   z PANEL group shape colour size fill alpha stroke
    1 1 1                A, B     1    -1    19  black  1.5   NA    NA    0.5
    2 2 2       1, 2, 3, 4, 5     1    -1    19  black  1.5   NA    NA    0.5
    3 3 3 function (x) , x/10     1    -1    19  black  1.5   NA    NA    0.5
    

    确实如此,现在您只需编写自定义几何面板绘图函数即可在绘图中描绘此列表,为此我推荐上面的链接。

    下面唯一要做的就是在绘制点之前打印z,并接受z作为可选的审美:

    MyGeom <- ggproto(
      "MyGeom", GeomPoint,
      draw_panel = function(data, panel_params, coord, na.rm = FALSE) {
        print(data$z)
        GeomPoint$draw_panel(data, panel_params, coord, na.rm = FALSE)
      },
      optional_aes = "z"
    )
    

    现在您需要一个指向MyGeom 的层的包装器:

    geom_mine <- function (mapping = NULL, data = NULL, stat = "identity", position = "identity", 
                             ..., na.rm = FALSE, show.legend = NA, inherit.aes = TRUE) 
    {
      layer(mapping = mapping, stat = stat, geom = MyGeom, 
            position = position, show.legend = show.legend, inherit.aes = inherit.aes, 
            params = list(na.rm = na.rm, ...))
    }
    

    您现在可以在绘图中使用它:

    ggplot(mydf) + geom_mine(aes(x = x, y = y, z = z))
    
    [[1]]
    [1] "A" "B"
    
    [[2]]
    [1] 1 2 3 4 5
    
    [[3]]
    function (x) 
    x/10
    

    瞧,它制作了情节并打印了z,就像我们说的那样。

    希望这些指点有所帮助!

    【讨论】:

    • 问题是我有两个在真实场景中完全不同的data.frames。我需要在数据框中放置一个带有数据框的列表,这意味着该数据框将重复与第一个数据框的行数相同的次数。在我的情况下不是一个好主意(有很多数据)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-08
    • 2013-06-17
    • 2017-02-01
    • 2017-08-31
    • 2019-08-22
    相关资源
    最近更新 更多