首页 > 解决方案 > 最终输出文档中混合文本和图形输出的错误顺序

问题描述

在 for 循环中,我决定创建一些图形和相关表格。

这些表是用writeLines()和创建的print()

为了创建我使用的图形plot(), boxplot(), mtext(), text(), axis(). 因此,一个图形是通过许多步骤创建的。它自己的每个图形都是完整且漂亮的。

我的问题是:当我在 Rstudio 中编织 markdown 文档时,图形和表格不在正确的位置。第一个图形显示在第二个应该是或稍早一点的地方,在cor.test.default()告诉我一个警告之后。明确地,它在 for 循环的下一次传递中显示。

问题的结论

特殊情况下,除图形外,还产生文字输出混杂

为了重现问题,我创建了一些数据所有计算都收集在“workingChunk”中

为了演示这个问题,我在最后使用了块“循环”。所以先读最后一块

在第二个循环中,在函数 cor.test() 发出警告之后,第一个图形在循环的第二个通道期间被放置在输出中。

在函数 cor.test() 发出警告之后,在循环的第三次通过期间,第二个图形也被放置在输出中。等等。

我找到了解决这个问题的方法,但它并不是很方便:当我用单个块调用替换 for 循环时,输出的顺序正确。

所以我确定问题的原因是for循环和函数cor.test()的交互

这是示例代码(大约 140 行):

---
title: "Test graphic & textual output"
output:
  pdf_document: default
  word_document: 
  html_document:
    df_print: paged
---

```{r setup, include=FALSE}

knitr::opts_chunk$set(echo = TRUE)

```

```{r creatingData, echo=TRUE}
### {r creatingData, echo=TRUE}
# creating some data
a.df <- data.frame(height=c(1:19),
                   width=c(21:39)*10,
                   depht=c(41:59)*20,
                   group=c(1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3))
a.df$groupF <- as.factor(a.df$group)

Vars <- names(a.df)[c(1:3)]
```

```{r workingChunk, echo=TRUE, eval=FALSE}
    cat("\n===================================================================\n",
        "following the calculations for:\n",
        "YVar:",YVar, "\n Group:", "group", "\n")

    # Daten für Auswertung extrahieren
    selvar <- c("group","groupF", YVar)

    # Datensätze mit Fehlwerten in der Zielvariablen ausschließen!
    a.sub <- a.df[ complete.cases(a.df[ , selvar]), selvar]   

    # print(str(a.sub))

    ## Tabelle für gruppierte Zielgrößen
    mT <- table(a.sub[ , c("groupF", YVar)])
    print(ftable(addmargins(mT)))  ## absolute Häufigkeiten
    writeLines("\n")

    if (runCorTest) {
        ## calculating Spearmans correlation
        myCorTest <- try(cor.test(a.sub[["group"]], a.sub[[YVar]], 
                              method = "spearman", alternative = "two.sided" ))

        print(myCorTest)
        writeLines("\n")
    }

## preparing the grafic
     GL.x1 <- levels(a.sub[["groupF"]])  ## grouplabels

     # Calculating the range of Y
     my.ylim <- c(min(a.sub[[YVar]], na.rm = TRUE), max(a.sub[[YVar]], na.rm = TRUE))

     at.x <- c(1:length(GL.x1))    ## Labelpositionen anlegen
     G.data <- vector("list", length(GL.x1))    ## Vektoren für die Daten der Gruppen anlegen

     # Daten der Gruppen herausziehen 
     G.data <- split(a.sub[[YVar]], a.sub["groupF"])
     # print(str(G.data))

## drawing emtpy plot
     cat("\n\n>>> Here should be placed the Grafik for:",YVar, "<<<\n")
     plot( x = NA, y = NA, type = "n",
           main = YVar,
           xlim = c( 1, length( GL.x1)) + c( -0.6, 0.6),
           ylim = my.ylim, 
           xlab = NA, ylab = NA,
           axes = FALSE, frame.plot = TRUE)

     # X-axis 
     axis( 1, las = 1, labels = FALSE)
     mtext(GL.x1, at = at.x, cex=0.8, side = 1, line = .3)

     # Y-axis
     axis( 2, las = 1)

## drawing the data 
     for (i in 1:length(G.data)){
        boxplot(G.data[i], # col = "white",
                 at = at.x[i], range = 0, add = TRUE,
                 boxwex = 0.6, yaxs = "i", axes = FALSE)
     }

```

```{r, loops, echo=FALSE}
 cat("\n===================================================================",
    "\n===================================================================\n",
    "calling the workingChunk within a for loop without executing cor.test()",
    "\n works fine!!",
    "\n===================================================================",
    "\n===================================================================\n")

runCorTest <- FALSE
for ( YVar in Vars) {
  <<workingChunk>>
}


cat("\n===================================================================",
    "\n===================================================================\n",
    "calling the workingChunk within a for loop with executing cor.test() ",
    "\n mixes up the textual output and the graphics!!",
    "\n===================================================================",
    "\n===================================================================\n")

runCorTest <- TRUE
for ( YVar in Vars) {
  <<workingChunk>>
}


cat("\n===================================================================",
    "\n===================================================================\n",
    "calling the workingChunk with executing cor.test() ",
    "\n workarround without a for loop works fine!!",
    "\n===================================================================",
    "\n===================================================================\n")

runCorTest <- TRUE
YVar <- Vars[1] 
<<workingChunk>>

YVar <- Vars[2] 
<<workingChunk>>

YVar <- Vars[3] 
<<workingChunk>>

```

标签: rr-markdownknitr

解决方案


不是真正的答案,而是更短的测试用例和解决方法:

---
title: "Test graphic & textual output"
output:
  html_document:
    df_print: paged
  word_document: default 
  pdf_document: 
    keep_tex: yes
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

```{r}
foo <- function(letter, warn) {
    cat("Doing", letter, "\n")
    print(letter)
    if (warn) warning(letter)
    cat("Graphic for", letter, "goes here", "\n")
    plot(1, main = letter)
}
```

# with loop and with warning

```{r}
for (letter in letters[1:3])
    foo(letter, TRUE)
```

# with loop and without warning

```{r}
for (letter in letters[1:3])
    foo(letter, FALSE)
```

# without loop and with warning

```{r}
foo("a", TRUE)
foo("b", TRUE)
foo("c", TRUE)
```

# with loop and with suppressed warning

```{r warning=FALSE}
for (letter in letters[1:3])
    foo(letter, TRUE)
```

除了删除所有数据处理之外,我还从命名块切换到了函数,我发现它在 R 中更惯用。不过,这并没有改变奇怪的顺序。

如果警告消息在您的情况下并不重要,您可以使用最后显示的解决方法:使用块选项抑制警告会warning=FALSE恢复排序。


推荐阅读