代码之家  ›  专栏  ›  技术社区  ›  klamsi

带有ggplot in for循环的绘图未编译为PDF

  •  1
  • klamsi  · 技术社区  · 6 年前

    我使用knitR(.Rnw)创建了一个报告,将其编译为PDF。因为我想为每个问题绘制相同的图,所以我在for循环中创建了一个图。不幸的是,我在PDF中得到了一个警告,但我不知道是什么导致了错误。。。

    我认为问题从这里开始:循环在R中运行良好,但不能编译为PDF(请参阅下面的全部代码)。我尝试了各种标签、打印功能和其他东西,但找不到解决方案。

    <<echo=FALSE, warning=T, message=F>>=
    
    for(i in 1:3){
      cat(paste("\\subsection{",titel[i],"}\n", sep=""))
      cat(paste("Figure \\ref{class",i,"} \n", sep=""))
       cat(paste("\\begin{figure}[H] \n", sep=""))
       cat(paste("\\begin{center} \n", sep=""))
         cat(paste("\\includegraphics[width=1\\textwidth,", 
                "height=.47\\textheight,keepaspectratio]{class",i,".pdf}\\caption{",titel[i],"}\n", sep=""))
    
        cat(paste("\\label{class",i,"}" \n, sep=""))
        cat(paste("\\end{center} \n",sep=""))
      cat(paste("\\end{figure} \n",sep=""))
    
    
    
      p <- ggplot(data[!is.na(data$F17),], aes_string(x=Fragen[i], y="..prop..", group = "1", fill="F17"))+ 
           geom_bar()+
           facet_grid(F17~.)+
           geom_text(aes(label = scales::percent(..prop..),
                  y= ..prop.. ), stat= "count", vjust = -.5, size=3) + 
           ylab("Prozent")+
           xlab(titel[i])+
           scale_fill_manual(name="Individuals", values=colorScheme)#+
           #theme_mine
    
    
     pdfnam<-paste("class",i,".pdf",sep="") #produce a plot for each class
     pdf(file=pdfnam,width=12, height = 4)
     #gridExtra::grid.arrange(p, q)
     print(p)
     dev.off()
    }
    
    @
    

    以下是复制的全部代码:

    \documentclass{article}
    
    \usepackage{amsmath,amssymb,amstext}
    \usepackage{graphicx}
    \usepackage{geometry}
    \geometry{top=15mm, left=25mm, right=25mm, bottom=25mm,headsep=10mm,footskip=10mm} 
    \usepackage{xcolor}
    \usepackage{float}
    \usepackage[T1]{fontenc} % Umlaute
    \usepackage[utf8]{inputenc}
    \inputencoding{latin1}
    
    \begin{document}
    \parindent 0pt
    
    \title{title} 
    \maketitle
    
    <<echo=FALSE, warning=FALSE, message=FALSE>>=
    library(ggplot2)
    library(reshape)
    library(knitr)
    library(doBy)
    library(dplyr)
    
    
    opts_chunk$set(fig.path='figure/graphic-', fig.align='center', fig.show='hold',fig.pos='!ht',
               echo=FALSE,warning = FALSE) 
    
    @
    
     <<echo=FALSE, warning=FALSE, message=F>>=
    
     # data and other useful stuff
    
     data <- data.frame(F1 = c("A", "A", "B", "C"), # answers to question 1, ...
                        F2 = c("A", "B", "B", "C"),
                        F3 = c("A", "B", "C", "C"),
                        F17 = c("K", "L", "L", "M")) # K, L and M are a certain individual. L answered twice.
    
     # colour scheme:
     GH="#0085CA"; H="#DA291C"; BV="#44697D"
     colorScheme <- c(BV, H, GH)
    
     # individual theme for plots:
    theme_mine = theme(plot.background = element_rect(fill = "white"),
                   panel.background = element_rect(fill = "white", colour = "grey50"),
                   text=element_text(size=10, family="Trebuchet MS"))
    
    # a vector with the variable names from "data" (F1, F2, F3).
    Fragen <- c(paste0('F',seq(1:3), sep=""))
    
    # question title for labeling the plots:
    titel <- c("Q1", "Q2", "Q3", "Q17")
    
    @
    
    
    \begin{figure}[h]
    \begin{center}
    <<echo=FALSE, fig.width=9.6, fig.height=6, warning=FALSE>>=
    
    p <- ggplot(data, aes(x=F17))+
         geom_bar(fill = colorScheme)+
         xlab(titel[4])+
         #geom_text(aes(label = scales::percent(..prop..),
         #          y= ..prop.. ), stat= "count", vjust = -.5, size=3) + 
         ylab("Absolut")+
         theme_bw()
         #theme_mine   # does not work properly yet.
    p
    
    @
    \caption{figa}
    \label{figa}
    \end{center}
    \end{figure}
    
    \section{individual plots}
    
    <<echo=FALSE, warning=T, message=F>>=
    
    # here is where the problem starts: the loop runs fine within R but does not compile to an PDF.
    
    for(i in 1:3){
      cat(paste("\\subsection{",titel[i],"}\n", sep=""))
      cat(paste("Figure \\ref{class",i,"} \n", sep=""))
       cat(paste("\\begin{figure}[H] \n", sep=""))
       cat(paste("\\begin{center} \n", sep=""))
         cat(paste("\\includegraphics[width=1\\textwidth,", 
                "height=.47\\textheight,keepaspectratio]{class",i,".pdf}\\caption{",titel[i],"}\n", sep=""))
    
        cat(paste("\\label{class",i,"}" \n, sep=""))
        cat(paste("\\end{center} \n",sep=""))
      cat(paste("\\end{figure} \n",sep=""))
    
    
    
      p <- ggplot(data[!is.na(data$F17),], aes_string(x=Fragen[i], y="..prop..", group = "1", fill="F17"))+ 
           geom_bar()+
           facet_grid(F17~.)+
           geom_text(aes(label = scales::percent(..prop..),
                  y= ..prop.. ), stat= "count", vjust = -.5, size=3) + 
           ylab("Prozent")+
           xlab(titel[i])+
           scale_fill_manual(name="Individuals", values=colorScheme)#+
           #theme_mine
    
    
     pdfnam<-paste("class",i,".pdf",sep="") #produce a plot for each class
     pdf(file=pdfnam,width=12, height = 4)
     #gridExtra::grid.arrange(p, q)
     print(p)
     dev.off()
    }
    
    @
    
    
    \end{document}
    

    提前多谢!

    1 回复  |  直到 6 年前
        1
  •  0
  •   Cedric    6 年前

    我想用你的可复制脚本传达几个建议。谢谢你提供,这很有帮助。

    通常,如果您有 plot print(ggplot_object) 在你的R区块中。在您的示例中,您试图混淆 begin{Figure} 使用R代码生成打印对象。你不需要使用它。Knitr将提供创建完整打印对象的工具,指向地物路径(默认),该路径与 .Rnw 剧本下面我给你举一个如何做到这一点的例子。

    唯一的缺点是,如果您尝试读取tex文件,它的渲染效果不如您自己创建的代码那么好( 我的意思是当你 编辑您的tex文件,所有内容都在一行中,但这不是对knitr的批评,knitr太好了 ). 您也尝试过的另一种选择是将图形保存在一个文件夹中的某个位置,然后使用tex命令加载它。在下面的示例中,我使用您的脚本为您提供了一个如何以这种方式包含地物的示例。我希望这对你有用。

    \documentclass{article}
    
    \usepackage{amsmath,amssymb,amstext}
    \usepackage{graphicx}
    \usepackage{geometry}
    \geometry{top=15mm, left=25mm, right=25mm, bottom=25mm,headsep=10mm,footskip=10mm} 
    \usepackage{xcolor}
    \usepackage{float}
    \usepackage[T1]{fontenc} % Umlaute
    \usepackage[utf8]{inputenc}
    \inputencoding{latin1}
    \usepackage{hyperref}
    \begin{document}
    \parindent 0pt
    
    \title{title} 
    \maketitle
    
    <<echo=FALSE, warning=FALSE, message=FALSE>>=
    library(ggplot2)
    library(reshape)
    library(knitr)
    library(doBy)
    library(dplyr)
    
    
    opts_chunk$set(fig.path='figure/graphic-', fig.align='center', fig.show='hold',fig.pos='!ht',
               echo=FALSE,warning = FALSE) 
    
    @
    
    <<echo=FALSE, warning=FALSE, message=F>>=
    
     # data and other useful stuff
    
     data <- data.frame(F1 = c("A", "A", "B", "C"), # answers to question 1, ...
                        F2 = c("A", "B", "B", "C"),
                        F3 = c("A", "B", "C", "C"),
                        F17 = c("K", "L", "L", "M")) # K, L and M are a certain individual. L answered twice.
    
     # colour scheme:
     GH="#0085CA"; H="#DA291C"; BV="#44697D"
     colorScheme <- c(BV, H, GH)
    
     # individual theme for plots:
    theme_mine = theme(plot.background = element_rect(fill = "white"),
                   panel.background = element_rect(fill = "white", colour = "grey50"),
                   text=element_text(size=10, family="Trebuchet MS"))
    
    # a vector with the variable names from "data" (F1, F2, F3).
    Fragen <- c(paste0('F',seq(1:3), sep=""))
    
    # question title for labeling the plots:
    titel <- c("Q1", "Q2", "Q3", "Q17")
    
    @
    
    First chunk uses the knitr output to place the figures, if you use ggplot don't
    forget to print your plot : \textbf{print(p)} otherwise it won't work . All your
    arguments are passed through chunk options. So where you tried to have them in the text,
    they are simply placed as other options to your chunk (see below). I have used
    the following options to reproduce your example.
    \begin{itemize}
    \item fig.width=9.6
    \item fig.height=6
    \item fig.pos='h',
    \item fig.cap="figa"
    \item fig.lp="figa"
    \item fig.align='center'
    \end{itemize}
    
    <<echo=FALSE, fig.width=9.6, fig.height=6, warning=FALSE, fig.pos='h', fig.cap="figa",fig.lp="figa", fig.align='center'>>=
    
    p <- ggplot(data, aes(x=F17))+
         geom_bar(fill = colorScheme)+
         xlab(titel[4])+
         #geom_text(aes(label = scales::percent(..prop..),
         #          y= ..prop.. ), stat= "count", vjust = -.5, size=3) + 
         ylab("Absolut")+
         theme_bw()
         #theme_mine   # does not work properly yet.
    print(p)
    
    @
    
    
    
    
    \section{individual plots}
    
    For individual plots we will use your script to generate the figure environment.
    To produce latex you need to pass the option 'asis'.
    
    <<generate_latex,echo=FALSE, warning=T, message=F, results='asis'>>=
    for(i in 1:3){
      cat(paste("\\subsection{",titel[i],"}\n", sep=""))
      cat(paste("Figure \\ref{class",i,"} \n", sep=""))
       cat(paste("\\begin{figure}[H] \n", sep=""))
       cat(paste("\\begin{center} \n", sep=""))
         cat(paste("\\includegraphics[width=1\\textwidth,", 
                "height=.47\\textheight,keepaspectratio]{class",i,".pdf}\\caption{",titel[i],"}\n", sep=""))
        cat(paste("\\label{class",i,"} \n", sep=""))
        cat(paste("\\end{center} \n",sep=""))
      cat(paste("\\end{figure} \n",sep=""))
    }
    @
    Now we need to save those figures.  By default in knitr figures are saved in the \textit{figure}
    subfolder and path is set to \textit{figure/myfigure} in the includegraphics
    command in the tex file.
    
    <<plot,echo=FALSE, warning=T, message=F, fig.keep='all',fig.show='hide', results='hide'>>= 
    for(i in 1:3){
      p <- ggplot(data[!is.na(data$F17),], aes_string(x=Fragen[i], y="..prop..", group = "1", fill="F17"))+ 
           geom_bar()+
           facet_grid(F17~.)+
           geom_text(aes(label = scales::percent(..prop..),
                  y= ..prop.. ), stat= "count", vjust = -.5, size=3) + 
           ylab("Prozent")+
           xlab(titel[i])+
           scale_fill_manual(name="Individuals", values=colorScheme)#+
           #theme_mine
      print(p)
    }
    @
    Now the other way to do it, as in sweave is just to save the plot where you
    want, this is the old sweave way, which I tend to use, I gave some explanation
    on how to arrange folders
    \href{https://stackoverflow.com/questions/46920038/how-to-get-figure-floated-surrounded-by-text-etc-in-r-markdown/46962362#46962362}{example script}
    In sweave you save those files using pdf() or png() or
    whatever device and set the graphics path to those figures using
    \textit{\\graphicspath{{/figure}}} in the preamble. If you want to set your
    graphics path to another folder you can set path using command like
    \textit{\\graphicspath{{../../figure}}}. This will set your path to the
    grandparent folder.
    
    Here I'm creating a directory, if existing, the code will still proceed with no
    warnings : \textit{dir.create(imagedir, showWarnings = FALSE)}.
    
    <<plot_manual,echo=FALSE, warning=T, message=F,results='hide'>>=
    imagedir<-file.path(getwd(), "figure")
    dir.create(imagedir, showWarnings = FALSE) # use show warning = FALSE
    pdfnam<-paste0(imagedir,"/class4.pdf") #produce a plot for each class
    pdf(file=pdfnam,width=8, height = 4)
    for(i in 4){
      p <- ggplot(data[!is.na(data$F17),], aes_string(x=Fragen[i], y="..prop..", group = "1", fill="F17"))+ 
          geom_bar()+
          facet_grid(F17~.)+
          geom_text(aes(label = scales::percent(..prop..),
                  y= ..prop.. ), stat= "count", vjust = -.5, size=3) + 
          ggtitle("manually saved plot")+
          ylab("Prozent")+
          xlab(titel[i])+
          scale_fill_manual(name="Individuals", values=colorScheme)
      print(p)
    }
     dev.off()
    @
    \subsection{section 4}
    This is Figure \ref{class4} 
    \begin{figure}[H] 
     \begin{center} 
       \includegraphics[width=1\textwidth,height=.47\textheight,keepaspectratio]{figure/class4.pdf}
       \caption{Manually edited caption for figure 4}
       \label{class4} 
      \end{center}
    \end{figure} 
    
    \end{document}