在Rstudio、knitr和Rmarkdown中,有一些图表无法渲染。

6
我正在使用以下软件: Ubuntu 12.04 64位, R 3.0.2, RStudio 0.98.312, knitr 1.5, markdown 0.6.3, mgcv1.7-27。
我有一个包含多个代码块的Rmarkdown文档。在其中一个代码块中,我拟合了一个GAM,汇总了拟合结果并绘制了拟合曲线。问题是第一个图形能够呈现在输出文件中,而第二个图形却不能。这是该代码块的一部分:
fit <- gam(y ~ s(x), data=j0, subset= !is.na(x))
summary(fit) # look at non-missing only
plot(fit)

fit <- gam(y ~ s(sqrt(x)), data=j0, subset= !is.na(x))
summary(fit)
plot(fit)

mean(y[is.na(x)]) - mean(y[!is.na(x)])

除了输出直接从第二个plot语句转到下面的平均数计算外,一切都按预期呈现。平均值计算的结果正确显示。

如果我在代码块中再注释掉7行后的另一个plot调用,则缺失的图会正确显示。

有人对这里发生的事情有什么建议吗?

以下是更新内容:

概述-在调用Plot 2后的几行代码中,存在一些生成执行错误(变量未找到)的R代码,并且在此之后的几行代码中存在对Plot 3的调用。如果修复了代码错误,则会呈现Plot 2。如果未修复代码错误并注释掉对Plot 3的调用,则会呈现Plot 2。问题取决于使用相同变量“fit”存储不同拟合结果。如果将每个拟合分配给不同的变量,则Plot 2可以正常呈现。

我不明白在成功执行多行代码后进行的更改如何(似乎回顾地)防止Plot 2呈现。

可重现的示例:

Some text.

```{r setup}
require(mgcv)

mkdata <- function(n=100) {
  x <- rnorm(n) + 5
  y <- x + 0.3 * rnorm(n)
  x[sample(ceiling(n/2), ceiling(n/10))] <- NA
  x <- x^2
  data.frame(x, y)  
} 
```

Example 1
=========

Plot 2 fails to render. (Using the same fit object for each fit.)

```{r example_1}
j0 <- mkdata()
attach(j0)
mx <- min(x, na.rm=TRUE)

fit <- gam(y ~ s(x), data=j0, subset= !is.na(x))
summary(fit)
plot(fit) # plot 1

fit <- gam(y ~ s(sqrt(x)), data=j0, subset= !is.na(x))
summary(fit)
plot(fit) #plot 2

mean(y[is.na(x)]) - mean(y[!is.na(x)]) # means calculation

# recode the missing values
j0$x.na <- is.na(x)
j0$x.c <- ifelse(x.na, mx, x) # ERROR in recode
detach()

attach(j0)
fit <- gam(y ~ s(sqrt(x.c)) + x.na, data=j0) # doesn't run because of error in recode
summary(fit) # this is actually fit 2
plot(fit) # plot 3 (this is actually fit 2)
detach()
```

Example 2
=========

Use separate fit objects for each fit. Plot 2 renders OK.

```{r example_2}
j0 <- mkdata()
attach(j0)
mx <- min(x, na.rm=TRUE)

fit1 <- gam(y ~ s(x), data=j0, subset= !is.na(x))
summary(fit1)
plot(fit1) # plot 1

fit2 <- gam(y ~ s(sqrt(x)), data=j0, subset= !is.na(x))
summary(fit2)
plot(fit2) #plot 2

mean(y[is.na(x)]) - mean(y[!is.na(x)]) # means calculation

# recode the missing values
j0$x.na <- is.na(x)
j0$x.c <- ifelse(x.na, mx, x) # ERROR in recode
detach()

attach(j0)
fit3 <- gam(y ~ s(sqrt(x.c)) + x.na, data=j0) # doesn't run because of error in recode
summary(fit3)
plot(fit3) # plot 3
detach()
```

Example 3
=========

Revert to using the same fit object for each fit. Plot 2 renders because plot 3 is commented out.

```{r example_3}
j0 <- mkdata()
attach(j0)
mx <- min(x, na.rm=TRUE)

fit <- gam(y ~ s(x), data=j0, subset= !is.na(x))
summary(fit)
plot(fit) # plot 1

fit <- gam(y ~ s(sqrt(x)), data=j0, subset= !is.na(x))
summary(fit)
plot(fit) #plot 2

mean(y[is.na(x)]) - mean(y[!is.na(x)]) # means calculation

# recode the missing values
j0$x.na <- is.na(x)
j0$x.c <- ifelse(x.na, mx, x) # ERROR in recode
detach()

attach(j0)
fit <- gam(y ~ s(sqrt(x.c)) + x.na, data=j0)
summary(fit) # this is actually fit 2
# plot(fit) # plot 3 (this is actually fit 2)
detach()
```

Example 4
=========

Plot 2 renders because later recode error is fixed.

```{r example_4}
j0 <- mkdata()
attach(j0)
mx <- min(x, na.rm=TRUE)

fit <- gam(y ~ s(x), data=j0, subset= !is.na(x))
summary(fit)
plot(fit) # plot 1

fit <- gam(y ~ s(sqrt(x)), data=j0, subset= !is.na(x))
summary(fit)
plot(fit) #plot 2

mean(y[is.na(x)]) - mean(y[!is.na(x)]) # means calculation

# recode the missing values
j0$x.na <- is.na(x)
j0$x.c <- ifelse(j0$x.na, mx, x) # error in recode fixed
detach()

attach(j0)
fit <- gam(y ~ s(sqrt(x.c)) + x.na, data=j0)
summary(fit)
plot(fit) # plot 3
detach()
```

日志文件:

> require(knitr); knit('reproduce.Rmd', encoding='UTF-8');
Loading required package: knitr


processing file: reproduce.Rmd
  |......                                                           |   9%
  ordinary text without R code

  |............                                                     |  18%
label: setup
  |..................                                               |  27%
  ordinary text without R code

  |........................                                         |  36%
label: example_1
  |..............................                                   |  45%
  ordinary text without R code

  |...................................                              |  55%
label: example_2
  |.........................................                        |  64%
  ordinary text without R code

  |...............................................                  |  73%
label: example_3
  |.....................................................            |  82%
  ordinary text without R code

  |...........................................................      |  91%
label: example_4
  |.................................................................| 100%
  ordinary text without R code


output file: reproduce.md

[1] "reproduce.md"

2
请提供一个可重现的示例。你的问题可能是由于你设置了块选项 fig.keep,但如果没有任何这方面的信息,那么这只是瞎猜。 - mnel
日志上写了什么? - Waldir Leoncio
1个回答

9

尽管人们一直警告不要使用attach(),但您仍然成为了另一个attach()的受害者。使用attach()非常容易出错。您在执行attach(j0)之后发生了这种情况:

j0$x.na <- is.na(x)
j0$x.c <- ifelse(x.na, mx, x) # ERROR in recode

当然,R无法找到对象x.na,因为它不存在于任何地方。是的,它现在在j0中,但除非您分离j0并重新附加它,否则它不会暴露给R。换句话说,attach()不会自动刷新,因此当您向j0添加更多变量时,它不会自我更新。所以简单的解决办法是:

j0$x.c <- ifelse(j0$x.na, mx, x)

我理解为什么你想使用attach() -- 可以避免在各处使用尴尬的j0$前缀,但你需要非常小心。除了我提到的问题之外,detach()也是有问题的,因为你没有指定要分离哪个环境,默认情况下,搜索路径上的第二个被分离,这不一定是你附加的那个环境,例如,你可能已经加载其他包到搜索路径上。因此你必须明确: detach('j0')
回到knitr: 如果你想知道发生了什么,我可以解释一下,但首先,你必须确保你的代码在传递给knitr之前实际上能够工作。当错误被消除时,你观察到的奇怪现象也将消失。

谢谢Yihui。我想我的问题更多地涉及knitr中的错误处理。从我的例子可以看出,我意识到了错误,并知道当代码块错误被修复后,knitr问题就不会出现。同一段代码在由knitr执行和在R中直接执行时产生不同的输出。这使得调试R代码更加困难,并暗示着一个特定的工作流程(在转移到knitr之前完全在R中进行调试)。这表明,knitr并没有像理想情况下那样与其执行的代码隔离开来。 - Ross Gayler
1
为了调试目的,最好设置块选项error=FALSE,或全局设置opts_chunk$set(error=FALSE);然后,每当块中出现错误时,knitr都会停止,您将能够使用常规方法如traceback()来调试代码。 - Yihui Xie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接