【问题标题】:How to build a layered plot step by step using grid in knitr?如何在knitr中使用网格逐步构建分层图?
【发布时间】:2013-07-06 10:33:06
【问题描述】:

对于研讨会附带的在线教程,我想强调网格包的使用(尤其是如何使用视口)。为此,我想逐步构建一个情节(即逐块)。在每个步骤/块之间,我想包含一些普通文本,以便更详细地解释每个步骤。

我如何告诉 knitr 不要单独评估一个块,而是在前一个块结束的地方开始评估?基本上,我想要添加到前一个块的结果中,而不是对块的新评估。

在下面的代码中,我在编织到 html 时在 .html 输出中得到 2 个图。第一个显示第一个块的结果(粉红色矩形和一些文本),第二个显示第二个块的结果(蓝色矩形)。我想要实现的是两个图 - 第一个显示第一个块的结果(如上),第二个显示第一个块的结果 + 第二个块的结果(粉红色矩形内的蓝色矩形)。 基本上,我想重现在 R 控制台中运行时这两个代码块的行为。蓝色矩形应放在粉色矩形内,不要单独绘制。

这是第一个块

```{r grid first vp, tidy = FALSE}
library(grid)
grid.newpage()

## draw a rectangle around the root vp and provide some text
grid.rect()
grid.text("this is the root vp", x = 0.5, y = 1, just = c("centre", "top"))

vp <- viewport(x = 0.5, y = 0.5, 
               height = 0.5, width = 0.5,
               just = c("centre", "centre"))

pushViewport(vp)

grid.rect(gp = gpar(fill = "pink"))
grid.text("this is our first vp", x = 0.5, y = 1, just = c("centre", "top"))
```

然后是一些解释性文字:

“好的,所以现在我们在x = 0.5y = 0.5 - just = c("centre", "centre")root 视口中间创建了一个视口,它是原始视口的一半高度和一半宽度——@987654326 @和width = 0.5

之后我们导航到这个视口 - pushViewport(vp),然后我们绘制了一个填充整个视口的矩形并用粉红色填充它 - grid.rect(gp = gpar(fill = "pink"))

请注意,我们还没有离开视口。这意味着,无论我们现在做什么,都将发生在当前活动的视口(粉红色的视口)中。为了说明这一点,我们将再次重复上面完全相同的代码(我们只是要更改填充颜色,以便更好地看到更改)。”

这是第二块

```{r grid second vp, tidy = FALSE}

vp <- viewport(x = 0.5, y = 0.5, 
               height = 0.5, width = 0.5,
               just = c("centre", "centre"))

pushViewport(vp)

grid.rect(gp = gpar(fill = "cornflowerblue"))
```

我有什么想法可以告诉 knitr '保留'之前的块中所做的任何事情,并将其作为当前块评估的'起点'?

【问题讨论】:

    标签: r knitr


    【解决方案1】:

    没有记录,但是这个功能已经存在了将近一年。要在整个编译过程中保持图形设备打开,您可以设置

    opts_knit$set(global.device = TRUE)
    

    我以为很少有人使用此功能,但似乎我错了。

    【讨论】:

    • 感谢一辉!这正是我一直在寻找的。使用 RStudio 不起作用,但这不是一个大问题,因为无论如何我都会直接通过 knitr 运行最终编译。再次感谢精彩的 knitr 包!
    • 天哪,我需要这个!
    【解决方案2】:

    您可以使用grid.grab() 捕获块末尾的场景,将其绘制到新块中,然后导航到最后一个视口(需要命名)。不幸的是,knitr 认为grid.grab() 应该会产生一个新的情节,我不知道如何解决这个问题。

    ```{r first, tidy = FALSE}
    library(grid)
    grid.newpage()
    
    ## draw a rectangle around the root vp and provide some text
    grid.rect()
    grid.text("this is the root vp", x = 0.5, y = 1, just = c("centre", "top"))
    
    vp <- viewport(x = 0.5, y = 0.5, 
                   height = 0.5, width = 0.5,
                   just = c("centre", "centre"), 
                   name="first")
    
    pushViewport(vp)
    
    grid.rect(gp = gpar(fill = "pink"))
    grid.text("this is our first vp", x = 0.5, y = 1, just = c("centre", "top"))
    scene <- grid.grab()
    ```
    
    ```{r second, tidy = FALSE, fig.keep='last'}
    grid.draw(scene)
    seekViewport("first")
    vp <- viewport(x = 0.5, y = 0.5, 
                   height = 0.5, width = 0.5,
                   just = c("centre", "centre"))
    
    pushViewport(vp)
    
    grid.rect(gp = gpar(fill = "cornflowerblue"))
    ```
    

    当然,从实用的角度来说,re-run the code from the first chunk要容易得多,

    ```{r second, tidy = FALSE}
    <<first>>
    vp <- viewport(x = 0.5, y = 0.5, 
                   height = 0.5, width = 0.5,
                   just = c("centre", "centre"))
    
    pushViewport(vp)
    
    grid.rect(gp = gpar(fill = "cornflowerblue"))
    ```
    

    【讨论】:

    • 谢谢巴蒂斯特!这两种选择都是可行的,但我真的想避免可能会混淆一些学生的冗余代码。特别是第二种方法非常简洁,但我不知道如何不回显第一个块的代码,而只回显第二个块的代码。
    • 您可以排除某些行被回显,例如echo = -c(1:13)
    猜你喜欢
    • 2020-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 2010-12-06
    相关资源
    最近更新 更多