shiny用法整理(三)

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

内容简介:继续整理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用法整理(三)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

游戏化实战

游戏化实战

[美]Yu-kai Chou / 杨国庆 / 华中科技大学出版社 / 2017-1 / 59.00

TED演讲人作品,罗辑思维、华为首席用户体验架构师、思科网络体验CTO推荐。 随书附有TED演讲中文视频及作者开设的游戏化初学者课程。作者为Google、乐高、华为、思科、斯坦福大学、丹麦创新中心等多家企业、机构提供高层培训与合作。 ********************** “我长期以来都在密切关注Yu-kai的研究成果。任何想要让工作、生活变美好的人都应该阅读这本书。” ......一起来看看 《游戏化实战》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具