Как сохранить многослойный PDF в R (через Sweave?)

Я искал ТАК, гуглил, читал ?pdf и не нашел возможности сохранить график в формате pdf со слоями, которые можно включать и выключать на полях средства просмотра pdf. Примером того, о чем я говорю, являются четырехъядерные топографические карты Геологической службы США, которые можно загрузить в формате PDF с несколькими слоями, например это (архивированный pdf).

Следующее предложение в справочном файле pdf() звучит зловеще, но я также хотел проверить, правильно ли я его истолковал:

 The R graphics model does not distinguish graphics objects at the level 
 of the driver interface.

Раньше я мог сохранять многослойные PDF-файлы в Illustrator, но этой программы больше нет в моем распоряжении. Возможно, кто-то может придумать обходной путь из R? Данные, которые я использую для отображения, большие, но вот игрушечный пример:

pdf("2objects.pdf")
plot(NULL, type = "n",xlim = c(0,1),ylim = c(0,1))
rect(0,.7,.7,0,border = "blue",lwd=2)
rect(.3,1,1,.3,border = "red",lty=2,lwd=2)
dev.off()

Это выглядит так (это png, но приведенное выше даст pdf) введите описание изображения здесь

Я хотел бы иметь красные и синие поля в качестве слоев с видимостью, которые можно включать и выключать из средства просмотра PDF.

Большое спасибо!

Изменить: найдена поток в R-help (re: @mnel), и это кажется невозможным. Я по-прежнему оставлю этот вопрос открытым на случай, если кто-то придумал отличный обходной путь R-tastic.

Изменить (5 сентября 2012 г.): я попытался сделать это с помощью Sweave и добился частичного успеха, используя обходной путь, опубликованный здесь. Этот метод создает один PDF-файл со «слоями», которые можно включать и выключать с помощью текста с гиперссылками под изображениями. Для этого используется трюк с «анимацией». Хотя это по-прежнему не является моим конечным желаемым результатом, его преимущество заключается в том, что он не зависит от конкретных программ просмотра PDF. Я все еще подожду, чтобы увидеть, опубликует ли кто-нибудь способ создания слоев, также известных как OCG, в документе Sweave, который я мог бы затем автоматизировать.

Изменить (13 сентября 2012 г.): я опубликовал свой прогресс в качестве ответа, используя код, упомянутый выше. Мне удалось заставить его работать в более сложной реальной ситуации без каких-либо изменений в коде с наложением различных административных и статистических границ в США. В этом случае я просто назвал разные наложения карт layer-0.pdf, layer-1.pdf и т. д., и все заработало без ошибок. Я все еще надеюсь, что со временем здесь появится что-нибудь получше.

Всем спасибо за комментарии


person tim riffe    schedule 04.09.2012    source источник
comment
Возможно, вам удастся заставить это работать, если вы используете tikzDevice. и может настроить tikz или pgf, чтобы получить PDF со слоями. К сожалению, пакет заархивирован, но он создает красивую графику (по крайней мере, когда я использовал его 2 года назад).   -  person mnel    schedule 05.09.2012
comment
спасибо @mnel, я пробовал это сейчас через Sweave и опубликую, если что-нибудь придумаю.   -  person tim riffe    schedule 05.09.2012
comment
Интересно, может ли ImageMagick сделать многослойный PDF-файл из двух отдельных?   -  person Aaron left Stack Overflow    schedule 06.09.2012
comment
просмотрел справочный форум ImageMagik и не нашел упоминания. Кажется, это должно быть в состоянии сделать это   -  person tim riffe    schedule 06.09.2012
comment
Вот вопрос с сайта tex SE, который делает это с пакетами ocgtools и содержит пример кода: tex.stackexchange.com/q /65096/2823   -  person Aaron left Stack Overflow    schedule 08.09.2012


Ответы (2)


Похоже, ответ (tex)animation — лучший, который я могу сейчас придумать. Следующий файл .Rnw создаст PDF-файл с рисунком в середине и двумя текстовыми гиперссылками под ним, которые независимо переключают видимость красного и синего полей. Я нашел код Tex, который делает эту работу здесь. Я еще не рассматривал предложение @Aaron's ocgtools, но доберусь до него. Спасибо всем за ваши предложения!

\documentclass{article}
%----------------------------------------------------------------%\
\usepackage[OT1]{fontenc}
\usepackage{Sweave}
\usepackage{animate}
\usepackage{hyperref}
\usepackage[margin=0.4in]{geometry}
%----------------------------------------------------------------%

\makeatletter
% command to create a toggle link
\newcommand{\ShowHideLayer}[3]{%
  % #1: anim No. (zero-based),
  % #2: layer No. (zero-based),
  % #3: link text
  \leavevmode%
  \pdfstartlink user {
    /Subtype /Link
    /Border [\@pdfborder]%
    /A <<
      /S/JavaScript
      /JS (
        \if at anim@useocg%
          if(a#1.fr[#2].state==true){
            a#1.fr[#2].state=false;
          }else{
            a#1.fr[#2].state=true;
          }
        \else
          if (a#1.fr[#2].display==display.visible){
            a#1.fr[#2].display=display.hidden;
          }else{
            a#1.fr[#2].display=display.visible;
          }
          this.dirty=false;
        \fi
      )
    >>
  }#3%
  \pdfendlink%
}

% command to create a link to show/hide all layers
\newcommand{\ShowHideAll}[2]{%
  % #1: anim No. (zero-based),
  % #2: link text
  \leavevmode%
  \pdfstartlink user {
    /Subtype /Link
    /Border [\@pdfborder]%
    /A <<
      /S/JavaScript
      /JS (
        var countvisible=0;
        for(var i in a#1.fr){
          \if at anim@useocg
            if(a#1.fr[i].state==true){countvisible++;}
          \else
            if (a#1.fr[i].display==display.visible){countvisible++;}
          \fi
        }
        if(countvisible){
          for(var i in a#1.fr){
            \if at anim@useocg
              a#1.fr[i].state=false;
            \else
              a#1.fr[i].display=display.hidden;
              this.dirty=false;
            \fi
          }
        }
        else{
          for(var i in a#1.fr){
            \if at anim@useocg
              a#1.fr[i].state=true;
            \else
              a#1.fr[i].display=display.visible;
              this.dirty=false;
            \fi
          }
        }
      )
    >>
  }#2%
  \pdfendlink%
}
\makeatother

\begin{document}

% heres the R-making of the plots, saved to working directory,
% which should be the folder containing this .Rnw file
% 3 versions of the same plot, one for each layer
<<echo = FALSE, hide = TRUE>>=
pdf("layer-0.pdf")
plot(NULL, type = "n", xlim = c(0, 1), ylim = c(0, 1), xlab = "", ylab = "")
dev.off()

pdf("layer-1.pdf")
plot(NULL, type = "n", xlim = c(0, 1), ylim = c(0, 1), axes = FALSE, xlab = "", ylab = "")
rect(0, .7, .7, 0, border = "blue", lwd = 2)
dev.off()

pdf("layer-2.pdf")
plot(NULL, type = "n", xlim = c(0, 1), ylim = c(0, 1), axes = FALSE, xlab = "", ylab = "")
rect(.3, 1, 1, .3, border = "red", lty = 2, lwd = 2)
dev.off()
@

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{center}
  %animated layer-set No. 0
  %                                          v-- frame rate ignored
  \animategraphics[width=1\linewidth,step]{1}{layer-}{0}{2}

  \ShowHideLayer{0}{1}{toggle red box}\\
  \ShowHideLayer{0}{2}{toggle blue box}\\
\end{center}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{document}
person tim riffe    schedule 13.09.2012

Я могу добиться этого через ggplot.

library(ggplot2)
df <- data.frame(x = c(1,10), y = c(20,40), class = 1:2)
layered_plot <- ggplot(df, aes(xmin = x, xmax = x + 1, ymin = y, ymax = y + 2, fill = class)) +
geom_rect() + 
opts(legend.position = "none") 
# Now save this as pdf
ggsave(layered_plot, file="p1.pdf")

введите здесь описание изображения

(Это просто версия png для иллюстрации, но когда я открываю pdf в Illustrator, я могу отключить отдельные слои по мере необходимости).

введите здесь описание изображения

person Maiasaura    schedule 04.09.2012
comment
Может ли это быть особенностью Illustrator? похоже, что при импорте pdf Illustrator разбивает все векторные элементы на отдельные объекты. Я надеялся найти решение, которое могло бы создать слой для одного окна и слой для другого, обходя Illustrator. Спасибо хоть! - person tim riffe; 04.09.2012
comment
Не уверен, что это проблема иллюстратора. Но если все, что вам нужно сделать, это отключить один или два элемента, это прекрасно работает. Вы также можете быстро сгруппировать элементы (например, оси), перетащив рамку вокруг него и нажав «Группировать». Это поможет уменьшить количество элементов. - person Maiasaura; 04.09.2012
comment
Как насчет сохранения файла с расширением .svg? Это сохранит слои (аналогично), но также полностью обойдет Illustrator (если у вас есть другая бесплатная программа для открытия). - person Maiasaura; 04.09.2012
comment
Я пробую это в Inkscape, но пока получается, что это большой объем ручного труда, который нелегко автоматизировать. Я продолжу этот путь и посмотрю, выйдет ли из него решение. Еще раз спасибо - person tim riffe; 05.09.2012
comment
Я уверен, что есть ветка r-help, где это обсуждается, но это не реализовано. - person mnel; 05.09.2012
comment
Это тема r-helpгде это обсуждается - person mnel; 07.09.2012
comment
Я видел это @mnel, поэтому сейчас я склоняюсь к обходному пути латекса / Sweave. У латекса, например, есть пакет 'ocgtools', но синтаксис пока что выше моего понимания. Я смог получить аналогичный, но неоптимальный результат с помощью Sweave, используя пакет латексной «анимации». - person tim riffe; 07.09.2012