Статьи

Makefiles для проектов R / LaTex

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

Если вы используете Mac или Linux, вы уже  make установили. Если вы используете Windows и у  вас  установлен Rtools , то у вас также будет  make. В противном случае пользователям Windows потребуется его установить. Одна реализация в  GnuWin .

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

Make полагается на то,  Makefile чтобы определить, что он должен делать. По сути, a  Makefile указывает, какие файлы должны быть сгенерированы в первую очередь, и как их генерировать. Поэтому мне нужно,  Makefile что указывает, что все файлы R должны быть обработаны в первую очередь, а затем файл LaTeX.

Прелесть в  Makefile том, что он будет обрабатывать только файлы, которые были обновлены. Он достаточно умен, чтобы не перезапускать код, если он уже был запущен. Так что, если ничего не изменилось, запуск make ничего не делает. Если изменяется только текстовый файл, при запуске make будет скомпилирован текстовый документ. Если код R изменился, при запуске make будет повторно запускаться код R для генерации новых таблиц и графиков, а затем повторная компиляция документа tex. Все, что я делаю, это печатаю,  make и он выясняет, что требуется

Makefile для LaTeX

Легко сказать, нужно ли компилировать латексный документ —  make просто нужно проверить, что PDF-версия документа старше, чем tex-версия документа. Вот простой,  Makefile который будет обрабатывать документ LaTeX.

TEXFILE= paper
$(TEXFILE).pdf: $(TEXFILE).tex
	latexmk -pdf -quiet $(TEXFILE)

Первая строка указывает имя моего файла, в данном случае  paper.tex. Вторая строка указывает, что файл pdf должен быть создан из файла tex, а последняя строка объясняет, как это сделать. Пользователи MikTeX могут предпочесть  pdftexify вместо  latexmk.

Чтобы использовать вышеизложенное  Makefile, скопируйте код в простой текстовый файл  Makefile и сохраните его в том же каталоге, что и ваш текстовый файл. Измените первую строку, чтобы использовать имя вашего текстового файла (без расширения). Затем введите  make из командной строки в том же каталоге, что и текстовый файл, и он должен сделать все необходимое для преобразования вашего текста в pdf.

Конечно, вы обычно не будете беспокоиться,  Makefile если это все, что он сделал. Но добавьте множество файлов R, и это станет очень полезным.

Makefile для R и LaTeX

Нам нужен способ, позволяющий  make определить, был ли запущен R-файл. Если файлы R запускаются с использованием

R CMD BATCH file.R

затем вывод сохраняется как  file.Rout. Тогда  make нужно только проверить,  file.Rout старше ли он  file.R.

Я также хотел бы убрать все пробелы из PDF-изображений, созданных в R, прежде чем поместить их в документ LaTeX. Есть хорошая команда,  pdfcrop которая делает это. (У вас уже должно быть это на Mac или Linux, а также на Windows, если вы используете MikTeX.) Поэтому я также хочу, Makefile чтобы я обрезал  все изображения, если они еще не были сделаны. Как только изображение обрезается, создается пустой файл формы,  file.pdfcropчтобы указать, что  file.pdf оно уже было обрезано.

Хорошо, теперь мы готовы к моему изумительному  Makefile.

# Usually, only these lines need changing
TEXFILE= paper
RDIR= .
FIGDIR= ./figs
 
# list R files
RFILES := $(wildcard $(RDIR)/*.R)
# pdf figures created by R
PDFFIGS := $(wildcard $(FIGDIR)/*.pdf)
# Indicator files to show R file has run
OUT_FILES:= $(RFILES:.R=.Rout)
# Indicator files to show pdfcrop has run
CROP_FILES:= $(PDFFIGS:.pdf=.pdfcrop)
 
all: $(TEXFILE).pdf $(OUT_FILES) $(CROP_FILES)
 
# May need to add something here if some R files depend on others.
 
# RUN EVERY R FILE
$(RDIR)/%.Rout: $(RDIR)/%.R $(RDIR)/functions.R
	R CMD BATCH $<
 
# CROP EVERY PDF FIG FILE
$(FIGDIR)/%.pdfcrop: $(FIGDIR)/%.pdf
	pdfcrop $< $< && touch $@
 
# Compile main tex file and show errors
$(TEXFILE).pdf: $(TEXFILE).tex $(OUT_FILES) $(CROP_FILES)
	latexmk -pdf -quiet $(TEXFILE)
 
# Run R files
R: $(OUT_FILES)
 
# View main tex file
view: $(TEXFILE).pdf
	evince $(TEXFILE).pdf &
 
# Clean up stray files
clean:
	rm -fv $(OUT_FILES) 
	rm -fv $(CROP_FILES)
	rm -fv *.aux *.log *.toc *.blg *.bbl *.synctex.gz
	rm -fv *.out *.bcf *blx.bib *.run.xml
	rm -fv *.fdb_latexmk *.fls
	rm -fv $(TEXFILE).pdf
 
.PHONY: all clean

Загрузите файл здесь.  Для большинства проектов я копирую этот файл в основной каталог своего проекта, и все, что мне нужно сделать, это изменить первые несколько строк. RDIR указывает, где хранятся файлы R, и  FIGDIR указывает, где хранятся цифры. Обычно я храню их вместе, но иногда они могут находиться в отдельных каталогах.

Теперь  make сделаем все необходимое — запустите R-файлы, обрежьте PDF-графику и обработайте латексный документ. Но он не будет делать никаких шагов, которые не нужно делать.

make R будет обрабатывать только файлы R

make view запустит просмотрщик PDF, после обновления файла PDF, если это необходимо.

make clean удалит все файлы, созданные с помощью latex или make, так что весь процесс должен быть запущен снова при следующей  make команде.

Обратите внимание, что все мои файлы R зависят от  functions.R. Это файл, который содержит специфичные для проекта функции. Если этот файл обновлен, все остальные R-файлы также нуждаются в обновлении.

Для многих проектов некоторые R-файлы будут зависеть от других, уже запущенных. Например,  read.R может считывать данные и переформатировать их для анализа, в то время как  plot.Rможет создавать некоторые графики, предполагая, что  read.R они уже выполнены. Чтобы убедиться, что  makeзнает об этой зависимости, нам нужно добавить строку

$(RDIR)/plot.Rout: $(RDIR)/plot.R $(RDIR)/functions.R $(RDIR)/read.R
	R CMD BATCH $<

Это должно быть вставлено, где у меня есть комментарий # May need to add something here if some R files depend on others.

Это  Makefile работает на Linux. Пользователи Mac и Windows должны будут заменить  evinceлюбую программу просмотра PDF, которую они предпочитают.