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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用for循环中的ggplot绘图不能编译为PDF相关的知识,希望对你有一定的参考价值。

我使用knitR(.Rnw)创建了一个报告,将其编译为PDF。由于我想为每个问题绘制相同的数字,我在for循环中创建了一个图。不幸的是,我在PDF中收到警告并且没有真正得到导致错误的原因...

这是我认为问题开始的块:循环在R中运行良好但不编译为PDF(参见下面的完整代码)。我尝试了各种标签,打印功能和其他东西,但无法找到解决方案。

<<echo=FALSE, warning=T, message=F>>=

for(i in 1:3){
  cat(paste("\subsection{",titel[i],"}
", sep=""))
  cat(paste("Figure \ref{class",i,"} 
", sep=""))
   cat(paste("\begin{figure}[H] 
", sep=""))
   cat(paste("\begin{center} 
", sep=""))
     cat(paste("\includegraphics[width=1\textwidth,", 
            "height=.47\textheight,keepaspectratio]{class",i,".pdf}\caption{",titel[i],"}
", sep=""))

    cat(paste("\label{class",i,"}" 
, sep=""))
    cat(paste("\end{center} 
",sep=""))
  cat(paste("\end{figure} 
",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}

egin{document}
parindent 0pt

	itle{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")

@


egin{figure}[h]
egin{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],"}
", sep=""))
  cat(paste("Figure \ref{class",i,"} 
", sep=""))
   cat(paste("\begin{figure}[H] 
", sep=""))
   cat(paste("\begin{center} 
", sep=""))
     cat(paste("\includegraphics[width=1\textwidth,", 
            "height=.47\textheight,keepaspectratio]{class",i,".pdf}\caption{",titel[i],"}
", sep=""))

    cat(paste("\label{class",i,"}" 
, sep=""))
    cat(paste("\end{center} 
",sep=""))
  cat(paste("\end{figure} 
",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}

非常感谢提前!

答案

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

通常你可以使用knitr来生成图表,前提是你的R块有plotprint(ggplot_object)in。在您的示例中,您尝试将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}
egin{document}
parindent 0pt

	itle{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 : 	extbf{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.
egin{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],"}
", sep=""))
  cat(paste("Figure \ref{class",i,"} 
", sep=""))
   cat(paste("\begin{figure}[H] 
", sep=""))
   cat(paste("\begin{center} 
", sep=""))
     cat(paste("\includegraphics[width=1\textwidth,", 
            "height=.47\textheight,keepaspectratio]{class",i,".pdf}\caption{",titel[i],"}
", sep=""))
    cat(paste("\label{class",i,"} 
", sep=""))
    cat(paste("\end{center} 
",sep=""))
  cat(paste("\end{figure} 
",sep=""))
}
@
Now we need to save those figures.  By default in knitr figures are saved in the 	extit{figure}
subfolder and path is set to 	extit{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
	extit{\graphicspath{{/figure}}} in the preamble. If you want to set your
graphics path to another folder you can set path using command like
	extit{\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 : 	extit{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 
ef{class4} 
egin{figure}[H] 
 egin{center} 
   includegraphics[width=1	extwidth,height=.47	extheight,keepaspectratio]{figure/class4.pdf}
   caption{Manually edited caption for figure 4}
   label{class4} 
  end{center}
end{figure} 

end{document}

以上是关于使用for循环中的ggplot绘图不能编译为PDF的主要内容,如果未能解决你的问题,请参考以下文章

使用 for 循环保存多个 ggplots

在 for 循环中以 pdf 格式保存 2-plot 图形

ggplot在pdf中嵌入字体

在ggplot中循环变量

Hbuilder中的less不能自动编译为css怎么办

ggplot中的for循环用于多个时间序列,即