如何在网格中排列html小部件图以便以pdf格式导出?

时间:2016-10-17 14:35:34

标签: r gridextra htmlwidgets networkd3

我想结合html小部件(主要是plotly和networkD3)的丰富性,可以将它们作为R中的网格中的绘图进行排列,以将它们导出为出版物的pdf图形。但是,如果我在R中创建一些html小部件对象并尝试使用 gridExtra :: grid.arrange()进行排列(请参阅下面的最小示例),我会收到以下错误:

Error in gList(list(x = list(links = list(source = c(0, 0), target = c(1,  : 
only 'grobs' allowed in "gList"

我搜索“将html小部件转换为grobs或plot”以便能够将它们排列在网格中,但找不到任何相关信息。我可以通过 htmlwidgets :: saveWidget()首先将html小部件保存为网站,然后使用 webshot :: webshot()并使用矢量图形编辑器(如Inkscape)手动排列图形。但是,尽管需要手动操作,但所有转换步骤都可能导致质量下降。

也许我可以用表或列以某种方式在LaTeX R-Markdown文档中排列图形,并指定纸张尺寸以适合我的情节。但不知怎的,感觉既不像是一个理想的解决方案,因为我可能想要在几个列和行中动态排列我的图形,添加标题等,这会使LaTeX / knitr中的排列变得非常复杂。

所以在我开始手动编织所有内容之前,我想问一下你是否知道更好的方法来安排一些html小部件图并将它们导出到R中的pdf?

最小例子

这是一个重现我的问题的小例子。假设我的目标是一个图表,它将两个不同过程的能量流相互比较(Sankey图与networkD3),通过在网格中将它们彼此相邻排列,如下所示: Exemplary arranged Sankey plots

这将是我的代码:

library(networkD3)
library(grid)
library(gridExtra)

## Create simplified Data
dfSankey <- list()
dfSankey$nodes <- data.frame(Name = c("Final Energy","Conversion Losses","Useful Energy"))
#1st process
dfSankey$links1 <- data.frame(Source = c(0,0),Target=c(1,2),Value=c(30,70))
#2nd process
dfSankey$links2 <- data.frame(Source = c(0,0),Target=c(1,2),Value=c(10,60))

## Draw Sankeys
plSankey1 <- sankeyNetwork(Links = dfSankey$links1, Nodes = dfSankey$nodes, Source = 'Source',
                          Target = 'Target', Value = 'Value', NodeID = 'Name')
plSankey2 <- sankeyNetwork(Links = dfSankey$links2, Nodes = dfSankey$nodes, Source = 'Source',
                           Target = 'Target', Value = 'Value', NodeID = 'Name')

#Arrange them next to each other
grid.arrange(plSankey1,plSankey2)

这会导致开头提到的错误消息。

Windows 7,R-Studio 0.99.903,R版本3.2.3,网格3.2.3,gridExtra 2.2.1,networkD3 0.2.13

1 个答案:

答案 0 :(得分:1)

在Amit Kohli的灵感之后,我开始尝试使用flexdashboard,各种Rmarkdown格式(html,pdf,isolides,...),Rpresentations - 但与我的目标相比,它们都有一些缺点。

在我看来,使用闪亮应用可以获得最佳视觉效果。然后使用 chrome 将生成的网站保存为pdf,最后使用briss裁剪pdf。

library(networkD3)

## Create simplified Data
dfSankey <- list()
dfSankey$nodes <- data.frame(Name = c("Final Energy","Conversion Losses","Useful Energy"))
#1st process
dfSankey$links1 <- data.frame(Source = c(0,0),Target=c(1,2),Value=c(30,70))
#2nd process
dfSankey$links2 <- data.frame(Source = c(0,0),Target=c(1,2),Value=c(10,60))

# Define UI for application that draws two Sankeys in columns
ui <- shinyUI(fluidPage(column(6,
                               h2("Process 1", align = "center"),
                               uiOutput("plot1.ui")
                               ),
                        column(6,
                               h2("Process 2", align = "center"),
                               uiOutput("plot2.ui")
                               )
))

# Define server logic required to draw the sankeys
server <- shinyServer(function(input, output) {

    #Render plot area relative to flow height
    output$plot1.ui <- renderUI({
      sankeyNetworkOutput("Plot1", height = "400px")
    })
    output$plot2.ui <- renderUI({
      sankeyNetworkOutput("Plot2", height=paste0(400*(70/100),"px"))
    })

    #Render Sankeys
   output$Plot1 <- renderSankeyNetwork({
     sankeyNetwork(Links = dfSankey$links1, Nodes = dfSankey$nodes, Source = 'Source',
                   Target = 'Target', Value = 'Value', NodeID = 'Name', fontSize = 15, nodeWidth = 10)
   })

   output$Plot2 <- renderSankeyNetwork({
     sankeyNetwork(Links = dfSankey$links2, Nodes = dfSankey$nodes, Source = 'Source',
                   Target = 'Target', Value = 'Value', NodeID = 'Name', fontSize = 15, nodeWidth = 10)
   })
})

# Run the application 
shinyApp(ui = ui, server = server)

编写一个闪亮的应用程序并完成所有这些手动转换只是为了在PDF格式中安排两个html小部件数字仍然感觉有点过分,但至少得到的pdf图片看起来非常令人愉快。

我希望这也可以帮助别人。