Сюжеты, надписи и титры внутри одного куска

Я создаю отчет о латексе, который выдает несколько графиков в вызове dlply. Разумеется, вызов dlply в одном блоке и для того, чтобы получить метки и подписи для изменения, я использую фрагмент из Steve Powell ниже. Подход работает, но кажется, что knitr не корректно форматирует вывод. Простой пример, демонстрирующий:

\documentclass{article}

\begin{document}
<startup,echo=FALSE,results='hide',message=FALSE,tidy=FALSE,warning=FALSE,fig.keep='all',comment=NA>>=
require(knitr)
require(ggplot2)
opts_knit$set(progress = F, verbose = F)
opts_chunk$set(comment=NA,
           tidy=FALSE,
           warning=FALSE, 
           message=FALSE, 
           echo=FALSE, 
           dpi=600,
           fig.width=6.75, fig.height=4, # Default figure widths
           dev=c("pdf",'tiff'),
           dev.args=list(pdf=list(NULL),tiff=list(compression='lzw')),
           error=FALSE)
@
<<plotloop,results='asis'>>=
for(x in seq(1,20)){
  x1<-data.frame(x=seq(1,10),y=seq(1,10))
  plt<-ggplot(data=x1,aes(x,y))+geom_point()
  figLabel=paste('Figure',x,sep='')
  capt<-paste('Caption for fig.',x)
  cat(knit(text=(paste("<<",figLabel,",fig.pos='ht',fig.cap='",capt,"'>>=\nplt\[email protected]",sep=''))))
}
@
\end{document}

Это почти работает. Беда в том, что knitr помещает закрытие \caption за пределы скобки \label, которое можно увидеть в фрагменте файла .tex ниже:

\begin{knitrout}
\definecolor{shadecolor}{rgb}{0.969, 0.969, 0.969}
\color{fgcolor}
\begin{figure}[ht]
\includegraphics[width=\maxwidth]{figure/Figure1} \caption[Caption for fig]{Caption for fig. 1\label{fig:Figure1}}
\end{figure}
\end{knitrout}

латекс может справиться с этим, если есть только несколько цифр, подобных этому, но с большим количеством графиков, он начинает их неправильно размещать. Я также пробовал это с помощью

fig.cap=paste('testLoop',seq(1,20))

и получите тот же результат.

Дальнейшие разъяснения: я нашел это на wikipedia Latex/Floats... страница:

Если вы хотите пометить фигуру, чтобы позже ее можно было ссылаться, вы должны добавить метку после заголовка (внутри, похоже, работает в LaTeX 2e), но внутри плавающей среды. Если он объявлен снаружи, он укажет номер раздела.

Мне кажется, что "внутри, похоже, работает в LaTeX 2e". Кажется, это работает только потому, что ошибка игнорируется несколько раз? я использую LaTeX2e < 2005/12/01 > . Я думаю, что бит кода находится в функциональной строке hook_plot_tex 120 hooks-latex.R:

fig2 = sprintf('\\caption%s{%s\\label{%s}}\n\\end{%s}\n', scap, cap,
                 paste(lab, if (mcap) fig.cur, sep = ''), options$fig.env)  

Это исправить?

fig2 = sprintf('\\caption%s{%s}\\label{%s}\n\\end{%s}\n', scap, cap,
                 paste(lab, if (mcap) fig.cur, sep = ''), options$fig.env)

Предложения? Я не знаком с процессом github... Спасибо!

Ответ 1

Короткий ответ - это проблема LaTeX, вызванная слишком многими командами \includegraphics и без разрывов страниц. Функция для выполнения нескольких фигур с надписями и надписями из цикла (с учетом Стив Пауэлл и Йихуэй):

plot.knit<-function(chunkLabel,#text for chunk label which is also used for figure file name
                capt,#text for caption
                plt)#plot object to be placed
   {
    cat(knit(text=(paste("<<",chunkLabel,",fig.pos='h',fig.cap='",capt,"'>>=\nplt\[email protected]",sep=''))))
}
cat('\\newpage')#some sort of page break must be inserted along the way to keep latex from breaking.

Это может быть изменено, чтобы добавить любые варианты блоков, которые вы хотели бы.

Длинный ответ: Вот что я сделал, чтобы заставить его работать. Я загрузил knitr из github, сделал предложенное изменение выше, скомпилировал и провел пример. Измененный код не изменил результат. Дальнейшее исследование ошибки латекса привлекло меня к часто задаваемому вопросу LaTeX, в котором говорится:

Ошибка также возникает в длинной последовательности срезов с плавающей точкой, без промежуточного текста. Если среда не будет соответствовать "здесь" (и вы позволили им пойти "здесь" ), никогда не будет разрыва страницы, и поэтому LaTeX никогда не сможет пересмотреть место размещения. (Конечно, поплавки не могут соответствовать "здесь" , если последовательность достаточно длительная: после заполнения страницы LaTeX не будет размещать больше плавающих чисел, что приведет к ошибке.

Методы разрешения могут включать переопределение поплавков с использованием спецификатора float пакетов [H] float, но вы вряд ли уйдете, не используя \clearpage время от времени.

Итак, я добавил

cat('\\clearpage')

после того, как графики будут сгенерированы на каждом этапе цикла. Это привело к тому, что ошибки не были выброшены, а цифры в правильных местах. Кроме того,

cat('\\newpage')

работает и, кажется, лучше справляется с размещением цифр 2 на странице в моем фактическом документе.

Рабочий код:

\documentclass{article}

    \begin{document}
<<startup,echo=FALSE,results='hide',message=FALSE,tidy=FALSE,warning=FALSE,fig.keep='all',comment=NA>>=
require(knitr)
require(ggplot2)
opts_knit$set(progress = F, verbose = F)
opts_chunk$set(comment=NA,
           tidy=FALSE,
           warning=FALSE, 
           message=FALSE, 
           echo=FALSE, 
           dpi=600,
           fig.width=6.75, fig.height=4, # Default figure widths
           dev=c("pdf",'tiff'),
           dev.args=list(pdf=list(NULL),tiff=list(compression='lzw')),
           error=FALSE)
@
<<plotloop,results='asis'>>=
for(x in seq(1,20)){
  x1<-data.frame(x=seq(1,10),y=seq(1,10))
  plt<-ggplot(data=x1,aes(x,y))+geom_point()
  figLabel=paste('Figure',x,sep='')
  capt<-paste('Caption for fig.',x)
  cat(knit(text=(paste("<<",figLabel,",fig.pos='h',fig.cap='",capt,"'>>=\nplt\[email protected]",sep=''))))
cat('\\newpage')
}
@

\end{document}