Shinyで作成した画像を保存したいと思いませんか?

Shiny

はじめに

Shinyアプリを使ってインタラクティブにグラフを表示できるのは便利ですが、せっかく作った図を画像として保存したい場面もありますよね。
実際私も、複数の条件でグラフを作成して比較する際に、画像を保存して並べて比較していました。
Print Screen等の画面を保存する方法で保存・比較をしていましたが、アプリにデフォルトで保存機能があると便利だと思いました。
そこでこの記事では、薬物動態の1コンパートメントモデルを例に、RとShinyを使って可視化したグラフをPNG画像として保存する方法をご紹介します。

全体のコード

以下は、アプリの全文コードです。コピペして動かすだけで実行できます。

まずは、Rstudioにコピペして、お試しください。

# 使用パッケージがインストールされていなければ自動でインストールし、読み込みます
packages <- c("shiny", "ggplot2", "Cairo")
lapply(packages, function(pkg) {
  if (!requireNamespace(pkg, quietly = TRUE)) install.packages(pkg)
  library(pkg, character.only = TRUE)
})

options(shiny.usecairo = TRUE)  # PNG出力時のフォントや描画精度を向上

ui <- fluidPage(
  titlePanel("Oral Administration PK Model"),
  sidebarLayout(
    sidebarPanel(
      numericInput("dose", "Dose (mg)", 100),
      numericInput("ka", "Ka (/hr)", 1.0),
      numericInput("ke", "Ke (/hr)", 0.1),
      numericInput("vd", "Vd (L)", 10),
      numericInput("f", "F (bioavailability)", 1.0),
      downloadButton("downloadPlot", "Download Plot as PNG")
    ),
    mainPanel(plotOutput("pkPlot"))
  )
)

server <- function(input, output) {
  # グラフ描画用のデータを生成する反応式
  plot_data <- reactive({
    time <- seq(0, 24, by = 0.1)
    conc <- input$f * input$dose * input$ka / (input$vd * (input$ka - input$ke)) *
      (exp(-input$ke * time) - exp(-input$ka * time))
    data.frame(Time = time, Concentration = conc)
  })

  # ggplotでプロットを作成する反応式
  make_plot <- reactive({
    ggplot(plot_data(), aes(x = Time, y = Concentration)) +
      geom_line(color = "blue") +
      labs(
        title = "Oral Administration Model",
        subtitle = paste("Dose:", input$dose, "mg | Ka:", input$ka, "/hr | Ke:", input$ke, "/hr | Vd:", input$vd, "L | F:", input$f),
        x = "Time (hr)",
        y = "Concentration (mg/L)"
      ) +
      theme_minimal(base_size = 16)
  })

  # 表示用グラフ
  output$pkPlot <- renderPlot({
    make_plot()
  })

  # PNG保存用処理
  output$downloadPlot <- downloadHandler(
    filename = function() paste0("pk_plot_", Sys.Date(), ".png"),
    content = function(file) {
      CairoPNG(filename = file, width = 1000, height = 800, res = 120)
      print(make_plot())
      dev.off()
    }
  )
}

shinyApp(ui, server)

このアプリでは、入力された薬物動態パラメータに応じた血中濃度の時間推移を表示し、そのグラフをPNG形式で保存することができます。


コード解説:画像保存の処理を詳しく見てみましょう

output$downloadPlot <- downloadHandler(
  filename = function() paste0("pk_plot_", Sys.Date(), ".png"),
  • 保存するファイル名のデフォルト表示を定義しています。Sys.Date() で当日の日付を取得してファイル名に付加します。
  • 実際に保存する際に、変更しても構いません。
  content = function(file) {
    CairoPNG(filename = file, width = 1000, height = 800, res = 120)
  • CairoPNG() により、高精度でPNG画像を描画する準備をします。解像度(res = 120)や画像サイズ(ピクセル単位)を指定可能です。
    print(make_plot())
  • make_plot()ggplot() による描画を行う関数で、これを出力します。
    dev.off()
  }
  • dev.off() は画像ファイルの描画デバイスを閉じる処理です。これをしないと保存が完了しません。

おわりに

このようにShinyアプリから高品質な画像を保存するのはとても簡単です。 様々な資料の作成や教育用スライドなど、静的な図が必要な場面でぜひ活用してみてください。

質問や応用したい内容があれば、コメント欄またはお問い合わせページからお気軽にどうぞ!

コメント

タイトルとURLをコピーしました