Подтвердить что ты не робот

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

Я обыскал SO, Googled, читал ?pdf и высыхал, сохраняя возможность сохранения сюжета в формате pdf со слоями, которые можно включать и отключать в поля просмотра PDF. Примером того, о чем я говорю, являются Quad-топографические карты USGS, которые можно загрузить как PDF файлы с несколькими слоями, например this (zipped 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)  enter image description here

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

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

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

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

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

Спасибо всем за ваши комментарии

4b9b3361

Ответ 1

Я могу добиться этого с помощью 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")

enter image description here

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

enter image description here

Ответ 2

Похоже, что ответ (tex) animation - лучшее, что я могу придумать сейчас. Следующий файл .Rnw создаст pdf файл с цифрой посередине и двумя текстовыми гиперссылками под ним, которые будут независимо отображать видимость красных и синих прямоугольников. Я нашел код Tex, который делает эту работу здесь. Я еще не смотрел предложение @Aaron 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 [email protected]%
          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 [email protected]
            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 [email protected]
              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 [email protected]
              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}