shiny用法整理(三)

栏目: R语言 · 发布时间: 7年前

内容简介:继续整理shiny的几个用法最近遇到的一个问题:Shiny的download本质是可以下载任何形式的文件,如表格、图片等等;shiny的官网介绍

继续整理shiny的几个用法

Download two or more plots in one download button

最近遇到的一个问题: 如何在Shiny上通过download按钮同时下载多张图片 。网上也有人提了相同的问题,但是没有给出合适的解决办法

Shiny的download本质是可以下载任何形式的文件,如表格、图片等等;shiny的官网介绍 http://shiny.rstudio.com/articles/download.html 中只提了常规的用法。经过我多次尝试,基本猜测shiny的 downloadHandler 一次点击只能下载一个对象(因为对于网页设计中,一次点击确实只能下载一个对象)

因此转化下思路,我可以将多个图片先保存到一个临时文件夹中,然后压缩后再通过shiny下载

网上查了下,也有人用这个方法来下载多个文件压缩后的压缩包,如 Shiny: download zip archive

现在模仿下就很简单了(将图片先存在 p 列表中,接着用 tempdir() 建个临时文件夹,然后用 ggsave 保存图片,最后用 zip 压缩):

output$download_plot <- downloadHandler(
  filename = function(){
    paste0("plots", ".zip")
  },
  # contentType = "image/png",
  content = function(file){
    fs <- c()
    tmpdir <- tempdir()
    setwd(tempdir())

    for(i in 1:length(var_name)) {
      filelist <- paste0(var_name[i], ".png")
      g <- p[[i]]
      fs <- c(fs, filelist)
      ggsave(filename = filelist, plot = g, device = "png", width = 16, height = input$plotheight, units = "cm", dpi = 600)
    }
    zip(zipfile = file, files = fs)
  }
)

由于 downloadHandler 是下载你指定的对象,所以如果不设置 contentType ,shiny程序会更具对象的拓展名来确定数据类型,这样通过压缩多张图片的方式,绕过了无法用 downloadHandler 来循环下载多张图片的问题

如果很N张图片需要下载,而且速度比较慢的话,可以考虑用Shiny的Progress indicators,参考之前的Shiny用法整理(一),然后对上面代码修改下(指定个progress,然后设置每出一张图,进度条就增加1/N,并给出提示信息~):

output$download_plot <- downloadHandler(
  filename = function(){
    paste0("plots", ".zip")
  },
  # contentType = "image/png",
  content = function(file){
    fs <- c()
    tmpdir <- tempdir()
    setwd(tempdir())

    progress <- shiny::Progress$new()
    on.exit(progress$close())

    progress$set(message = "Begin to download boxplots:", value = 0)

    for(i in 1:length(var_name)) {
      filelist <- paste0(var_name[i], ".png")
      g <- p[[i]]
      fs <- c(fs, filelist)
      ggsave(filename = filelist, plot = g, device = "png", width = 16, height = input$plotheight, units = "cm", dpi = 600)

      progress$inc(1/length(var_name), detail = "Please wait...")
    }
    zip(zipfile = file, files = fs)
  }
)

但是对于这个进度条的位置不太满意(默认是右下角),如果下个对这个进度条进行修改,则需要重新设置 .shiny-notification ,这个是notification的类,至于如何查到shiny的notification相关类有哪些,则可以查看shiny的CSS代码 https://github.com/rstudio/shiny/blob/master/inst/www/shared/shiny.css ,搜索下shiny-notification即可,其默认的CSS如下:

.shiny-notification {
  background-color: #e8e8e8;
  color: #333;
  border: 1px solid #ccc;
  border-radius: 3px;
  opacity: 0.85;
  padding: 10px 8px 10px 10px;
  margin: 2px;
}
而我们需要在Shiny的UI部分加入指定的CSS代码,可参考

Adjust size of Shiny progress bar and center it

,主要是修改notification的位置(当然也可以设置宽度和高度等等),如下:
tags$head(
    tags$style(
      HTML(".shiny-notification {
             position:fixed;
             top: calc(50% + 250px);;
             left: calc(50% + 500px);;
             }"
      )
    )
  )

至于为什么是修改notification,是因为进度条的style选的就是notification,因此上述用法在 showNotification 中也是通用的

Shiny App Usage Tracking

对于如何监控你的shiny app,shiny官方给出了一整套完整的方法,如果你是用shinyapps.io、RStudio Connect以及Shiny Server Pro,那么无需考虑这个,如果是使用free shiny,则需要借助第三方工具Google Analytics / Piwik,可参考官方文档 Shiny App Usage Tracking

出于在墙内的原因,Google Analytics工具我是无法使用的,而Piwik是基于PHP+Mysql的,由于其开源又功能的强大,所以想立马使用不太现实,所以我想寻找一种基于shiny或者R就能使用的简单监控系统,因为我只需要知道访问量和点击量就行

我先找到一个作者使用其自己的写的R代码来监听他在服务器上运行的所有shiny程序,其实是R代码来调用netstat命令来

实现的,这样可以简单统计用户访问量了,参考文章 How to monitor app usage on Shiny Server Open Source

但是这个方法并不能很好的解决我的需求,因此我还找了另一个作者提供的方法,使用shiny的一些插件来获取网页用户填写的信息,参考文章 Mimicking a Google Form with a Shiny app

按照作者的意思,其是mimicks a Google Form,将用户填写的提交的信息收集并存储起来,然后再可视化用于展示用户信息,那么在UI中只需要增加几个框用于用户填写信息

fluidRow(
      column(
        3, selectInput("usertype", h4("User Type", span("*", class = "mandatory_star")), choices = list("技术支持", "学术顾问", "其他"))
      ),
      column(
        3, textInput("userid", h4("User Name", span("*", class = "mandatory_star")), placeholder = "...")
      ), 
      column(
        3, textInput("projectid", h4("Project Id", span("*", class = "mandatory_star")), placeholder = "For example P20180100001")
      )
    )

然后再server中将填写的信息记录下来(包括日期等信息),然后存储到指定文件中

log_con <- data.frame("boxplot_count", input$usertype, input$userid, input$projectid, format(Sys.time(), "%Y-%m-%d-%H-%M"))
write.table(log_con, file = "log/tools.log", sep = "\t", row.names = F, col.names = F, quote = F, append = T)

关于shiny存储数据可以查看其官方文档 Persistent data storage in Shiny apps ,包括如果调用各个类型数据库等,我这只是简单使用Local storage

那么如何统计点击量呢,如果是一般按钮的点击,可以粗暴点用shiny基本用法中的,点击一次就计数一次,但是当我的情况是需要统计图片超链接的点击量,那么上述方法就不可行了

这是得借助shinyJS这个JS包来实现,其实这个需求对于正常的前端IT来说,就是一个JS命令的问题,那么用shinyJS则要其 onclick 函数来实现,现在在UI中设定好图片超链接的id,也就是类

div(
    tags$a(id = "count_id", tags$img(src="plot.png", width = "100%"), href = "http://xxx:3838/plot/"),
    tags$h3("Plot Tools", style = "color:#47a3da; font-family: sans-serif"),
)

然后再server中对于这个ID使用onclick事件,并记录点击相关信息

shinyjs::onclick(id = "count_id", {
    log_con <- data.frame("boxplot_count", input$usertype, input$userid, input$projectid, format(Sys.time(), "%Y-%m-%d-%H-%M"))
    write.table(log_con, file = "log/tools.log", sep = "\t", row.names = F, col.names = F, quote = F, append = T)
  })

这样结合上述,就能简单的实现用户的登录的记录以及超链接点击的记录等需求

本文出自于 http://www.bioinfo-scrounger.com 转载请注明出处


以上所述就是小编给大家介绍的《shiny用法整理(三)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Convergence Culture

Convergence Culture

Henry Jenkins / NYU Press / 2006-08-01 / USD 30.00

"Convergence Culture" maps a new territory: where old and new media intersect, where grassroots and corporate media collide, where the power of the media producer, and the power of the consumer intera......一起来看看 《Convergence Culture》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具