使用for循环中的ggplot绘图不能编译为PDF

时间:2017-12-28 15:45:42

标签: r pdf ggplot2 latex knitr

我使用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 个答案:

答案 0 :(得分:0)

我尝试使用可重现的脚本传达了一些建议。感谢您提供它,它有很多帮助。

通常您可以使用knitr生成图表,前提是您的R块中有plotprint(ggplot_object)。在你的例子中,你试图混淆一个 begin{Figure}使用R代码生成绘图对象。你不需要使用它。 Knitr将提供创建完整绘图对象的工具,指向图形路径(默认),该路径与.Rnw脚本位于同一文件夹中。我在下面给你一个如何做到这一点的例子。

唯一的缺点是,如果你试图读取你的tex文件,它就不会像你自己创建代码那样很好地呈现(我的意思是当你  编辑你的tex文件,一切都在一行,但这不是对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}