使用R web框架Shiny轻松构建生信交互式网站

做生信需要懂 R web框架 Shiny吗?
答案:不懂R Shiny的生信科研工作者不是好生信科研者


说说这几年我用web框架参与构建生信网站的项目(就是我搬的砖),1.某病的分型网站,就是输入某人的一些临床特征和基因信息,然后判断出此病人属于此病的那个亚型;2.遗传风险评估,就是输入某人的基因文件,判断评估此人在各种病上的遗传风险;3.药物查询/推荐系统,也是根据某人的基因信息,判断使用某药物的安全性、代谢剂量和疗效等;4.某单细胞数据库构建。··……

用处还是很多的,再来看看使用网站来投文章也是可以用的!用好了,投个NAR 的数据库或web 工具就是好几十分;或者作为某工具或算法的使用网站,也是文章的一大亮点啊!


不得不说web 网站框架也不是那么好学的,各种语言的web框架都有,但是作为生信人,强烈推荐大家使用 R shiny 开始, 用它搭建交互式网站入门只需3分钟,今天必须学会,以后需要就可以用起来了,免费的实操课,希望大家用心学,带大家入门并且把我构建好的网站目录结构送给大家,以后大家做网站就可以利用这个为基础框架做自己的网站,赶紧收藏起来哈!

Shiny 简介

Shiny(https://shiny.rstudio.com/app-stories/)是RStudio公司开发的R包,在R中使用它可以轻松开发交互式web应用
如果你还没有安装 Shiny 包,打开一个 R 会话,连接到互联网,然后运行

install.packages("shiny")

就可以安装。

特点

 只用几行代码就可以构建有用的web应用程序—不需要用JavaScript
 Shiny用户界面可以用纯R语言构建,有许多现成的小工具来展示图形、表格、输入框或输入对象,如果想更灵活,还可以直接用HTML、CSS和JavaScript来写
 采用反应式(reactive)编程模型,摒弃了繁杂的事件处理代码,这样你可以集中精力于真正关心的算法或功能的代码上

Shiny官方例子——使用Shiny say hello

运行 “say hello” 这个例子,

library(shiny)
runExample("01_hello")

绘制的直方图是基于faithful数据集。用户可以使用滑动条更改bins的数量,应用程序将立即响应输入。


Shiny 包有11 个内置示例,每个示例都演示了 Shiny 的工作原理,都是一个独立的 Shiny 应用程序。我们来看01 实例,了解此应用的web结构,浏览一下源代码,可以获得对shiny的初始印象。也可以通过认真阅读注释来进一步了解。

Shiny应用程序分为:用户界面定义(ui)、服务端脚本(Server)和 shinyApp
通信函数。这三部分的源代码都包含在app.R脚本里。用户界面 ( ui) 的对象控制应用程序的布局和外观,server函数包含您构建应用程序所需的响应函数。最后, shinyApp函数创建UI和服务器,构建 Shiny 应用程序。

ui

Hello Shiny示例的ui对象

library(shiny)
# Define UI for app that draws a histogram ----
ui <- fluidPage(
  # App title ----
  titlePanel("Hello Shiny!"),
  # Sidebar layout with input and output definitions ----
  sidebarLayout(
    # Sidebar panel for inputs ----
    sidebarPanel(
      # Input: Slider for the number of bins ----
      sliderInput(inputId = "bins",
                  label = "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)
    ),
    # Main panel for displaying outputs ----
    mainPanel(
      # Output: Histogram ----
      plotOutput(outputId = "distPlot")
    )
  )
)

server

Hello Shiny示例的server函数

# Define server logic required to draw a histogram ----
server <- function(input, output) {

  # Histogram of the Old Faithful Geyser Data ----
  # with requested number of bins
  # This expression that generates a histogram is wrapped in a call
  # to renderPlot to indicate that:
  #
  # 1. It is "reactive" and therefore should be automatically
  #    re-executed when inputs (input$bins) change
  # 2. Its output type is a plot
  output$distPlot <- renderPlot({

    x    <- faithful$waiting
    bins <- seq(min(x), max(x), length.out = input$bins + 1)

    hist(x, breaks = bins, col = "#75AADB", border = "white",
         xlab = "Waiting time to next eruption (in mins)",
         main = "Histogram of waiting times")

    })

}

该脚本会进行一个函数定义renderPlot,它使用请求的 bin 数量来计算绘制直方图
最后在app.R文件中,从加载 Shiny 包开始,并以调用结束shinyApp:

library(shiny)

# See above for the definitions of ui and server
ui <- ...

server <- ...

shinyApp(ui = ui, server = server)

每个 Shiny 应用程序都具有相同的结构:一个app.R包含ui和server. 你可以通过创建一个新目录并在其中保存一个app.R文件来创建一个 Shiny 应用程序。建议每个应用程序都位于唯一的目录中。

走一个通用的应用app

跑通了官方例子后,加快你学习脚步的方式就是应用,给大家走一个通用的应用框架,然后就可以按需使用起来,差什么做什么就可以很快的学会了!
先建立一个应用目录,其目录下的文件夹和r应用程序的脚本如下:


前面提到的ui 和server 在这里被我拆分成 ui.r 和 server.r, 这样能更好扩展应用结构,分别还建有 data 、docs、和www 目录,用来分别存放web 应用所需要的数据表、文档和图片。
下面我们一起来看 ui.r ,首先加载了应用中所用到的包,除 shiny 外,还应用了shinydashboard 包(http://rstudio.github.io/shinydashboard/index.html)来构建网站的页面结构,可以免去设计页面布局的一些烦恼,以及应用了reactable(https://github.com/glittershark/reactable)来可视化表格数据,和利用ggplot2来展示可视化图表,一个基础级的应用网站仅使用这些包就可以完成了,其具体用法见如下注释的脚本,如果要个性化自己的应用,看R包的使用方法修改就可以应用起来了。
ui.r:

#加载应用所需包
library(shiny)
library(shinydashboard)
library(reactable)
library(ggplot2)

shinyUI(dashboardPage(
    ## 指定主题色
        skin = "blue",
        ## 指定应用名称
        dashboardHeader(title = "DrugDB"),
        ## 指定页面菜单栏内容
        dashboardSidebar(
          sidebarMenu(
            ## 添加的菜单栏
            menuItem("主页", tabName = "dashboard", icon = icon("home")),
            menuItem("浏览", tabName = "widgets", icon = icon("th")),
            menuItem("搜索", tabName = "charts",icon = icon("search")),
            menuItem("关于我们", tabName = "about",icon = icon("dashboard"))        
          )
        ),
        ## Body content
        dashboardBody(
          tabItems(
            
        #第一个菜单栏的页面内容
            tabItem(tabName = "dashboard",
                    h1("欢迎来到DrugDB"),
                    p('DrugDB目的在于给用户提供与基因突变相关联的药*****'),
    #在dashboard的tab栏加入应用程序www文件夹中的图片
                    div(img(src="home_pic.jpg",height = 400,width=700)),
                    p('药物基因组学基因功能学与分子药理学的有机结合******。
                      我们致力于归纳总结这些药物基因组学的研究成果,为用药者提供重要的研究信息,提供用药指导。'),
                    div("图片来自:"),
                    a("Deep learning in pharmacogenomics: from gene regulation to patient stratification",href="https://www.google.com/")
                    
            ),
            
            # 第二个菜单栏的页面内容
            tabItem(tabName = "widgets",
                    h1("用药基因"),
                    fluidRow(
                      box(
                        title = "MTHFR", status = "primary", solidHeader = TRUE,
                        collapsible = TRUE,
                        div(class = "my-class", "该基因****")
                        
                      ),
                      box(
                        title = "XRCC1", status = "primary", solidHeader = TRUE,
                        collapsible = TRUE,
                        div(class = "my-class", "该基因编码**")
                      ),
                    ),
                    p("更多基因见本网站搜索栏"),
                    h1("药物统计"),
                    fluidRow(
                      sidebarPanel(
                        title = "药物类型",
                        radioButtons("inCheckboxGroup", "选择药物类型",
                                     c("化疗药物", "抗肿瘤药物", "抗凝药物",
                                       "高血脂药物","高血压药物","高血糖药物")),
                      ),
                      mainPanel(plotOutput("plot2", height = 250)),
                    )   
            ),
        
        # 第三个菜单栏内容
            tabItem(tabName = "charts",
                    h1("药物查询"),
                    reactableOutput("table")
            ),
        # 第四个菜单栏内容
            tabItem(tabName = "about",
                    h1("关于我们"),
                    fluidRow(
        # 在第四个菜单栏页面中放入展示docs文件下内容About.md
column(10,includeMarkdown("docs/About.md"))
                   )
            )
          )
        )
      )
)

server .r中定义了与用户交互响应的函数,server .r 脚本具体内容如下:

library(shiny)
library(shinydashboard)
library(reactable)
library(ggplot2)

shinyServer(function(input, output,session) {
    observe({
      x <- input$inCheckboxGroup
#读取应用程序data下的数据文件      drug_info=read.delim('./data/drug_info.txt',check.names=TRUE, stringsAsFactors=FALSE,sep = '\t')
     
      output$plot2 <- renderPlot({
        drug_info = drug_info[which(drug_info$drug_type==x),]
        drug_name =  paste(x,'作用基因',sep='')
        data = table(na.omit(drug_info$gene))
        data=data.frame(data)
        ggplot(data,aes(x=Var1, y=Freq)) + 
          geom_bar(stat="identity",fill="lightblue")+
          theme(text = element_text(family = "STHeiti"),axis.text.x = element_text(angle=90, hjust=1, vjust=1))+
          labs(x =drug_name, y = "作用基因的snp数")
      })

      output$table <- renderReactable({
        reactable(
          drug_info,
          ###指定所有列的格式
          defaultColDef = colDef(   
            align = "center",
            headerStyle = list(background = "lightblue")
          ),
          columns = list(
            c_drugname = colDef(name = "药物名称"),
            drug_type = colDef(name = "药物大类"),
            main_categroy = colDef(name = "药物子类"),
            clinical_level =colDef(name = "药物临床等级"),
            rs =  colDef(name = "基因位点"),
            chr=colDef(name = "染色体号"),
            ref=colDef(name = "位点参考"),
            alt=colDef(name = "位点变化"),
            pubmed_id = colDef(name = "PMID"),
            gene=colDef(name = "基因"),
            genotype_1=colDef(name ='基因型1',width = 100),
            genotype_2=colDef(name ='基因型2',width = 100),
            genotype_3=colDef(name ='基因型3',width = 100),
            annotation_1 =colDef(name ='药物疗效1',width = 300),
            annotation_2 =colDef(name ='药物疗效2',width = 300),
            annotation_3 =colDef(name ='药物疗效3',width = 300),
            rs = colDef(align = "center")
          ),
          bordered = TRUE,                   ###边线
          highlight = TRUE,                   ###高亮
          searchable=TRUE,                       ###搜索
          filterable=TRUE,                         ###过滤
          defaultPageSize=15,     ###分页                                           
          pageSizeOptions=c(10,15,20),
          showPageSizeOptions=TRUE,
          paginationType="jump"              
        )
      })
    })
  })

在server.r或ui.r 里run App后,用户的界面如下所示, 整个页面及菜单栏的就是利用dashbord来搭建的,在主页的菜单栏内容里给大家示例了如何插入图片和超链接。具体代码在ui.r 里,不涉及与用户的交互,是一个静态展示的页面。


浏览页面如下,示例了如何插入交互式图表,就是结合server的output$plot2来定义了响应函数;


搜索页面如下,示例了分页展示表格数据,并且提供筛选框和搜索框,又是使用server的 output$table来定义响应函数;


关于我们如下,一般就是此应用的使用说明或作者说明,示例了利用md 在页面上展示,


测试运行的伙伴在应用程序的docs里文件创建一个md文件即可,可以参考如下本示例文档,使用markerdown语法就行。


总结

Shiny 里 ui 涉及的就是用户页面可视化设计的代码,server里就是负责完成交互函数和读取数据等功能的代码,这个通用的app框架适用大多数基础应用,搞懂后即可定制化成自己的web应用。

©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容