Shiny-cheatsheet
作者:周彥通
1.安裝
install.packages("shinydashboard")
2.基礎知識
儀表盤有三個部分:標題、側邊欄,身體。下面是最最小的儀表面板頁面的UI:
# ui.R #library(shinydashboard)
dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody())
通過shinyApp()函數可以快速查看R控制台:
# app.R #
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody())
server <- function(input, output) { }
shinyApp(ui, server)
添加實用部分:
## app.R ##
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Basic dashboard"),
dashboardSidebar(),
dashboardBody(
# Boxes need to be put in a row (or column)
fluidRow(
box(plotOutput("plot1", height = 250)),
box(
title = "Controls",
sliderInput("slider", "Number of observations:", 1, 100, 50)
)
)
)
)
server <- function(input, output) {
set.seed(122)
histdata <- rnorm(500)
output$plot1 <- renderPlot({
data <- histdata[seq_len(input$slider)]
hist(data)
})
}
shinyApp(ui, server)
添加側邊欄:
下面將添加性能像tabs的菜單項,這與shiny中的tabPanels相似,當點擊菜單欄的時候,將在main body中顯示設置的不同的內容。為了實現這種功能,需要做到兩點,第一,在側邊欄dashboardSidebar 的sidebarMenu中添加menuItem,並用tabName設置其名稱,如下所示:
## Sidebar content
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", tabName = "widgets", icon = icon("th"))
)
)
第二,在dashboardBody中添加tabItem和tabItems,並設置tabName:
## Body content
dashboardBody(
tabItems(
# First tab content第一個標簽內容
tabItem(tabName = "dashboard",
fluidRow(
box(plotOutput("plot1", height = 250)),
box(
title = "Controls",
sliderInput("slider", "Number of observations:", 1, 100, 50)
)
)
),
# Second tab content第二個標簽內容
tabItem(tabName = "widgets",
h2("Widgets tab content")
)
)
)
默認顯示為“Dashboard”菜單:
當點擊“Widgets”時:
3.結構---Shiny and HTML
To understand how the parts of a dashboard work together, we first need to know how a Shiny UI is built, and how it relates to the HTML of a web page.在Shiny中的HTML標簽函數,比如div()和p()返回的對象可以呈現為HTML。例如,當您在R控制台運行這些命令,它將打印HTML:
# A basic div
div(class = "my-class", "Div content")
## <div class="my-class">Div content</div>
# Nested HTML tags
div(class = "my-class", p("Paragraph text"))
## <div class="my-class">
## <p>Paragraph text</p>
## </div>
一些函數返回更復雜的HTML片段,他們使用戶不必知道所有的所需的HTML來龍去脈創建諸如文本輸入或者側邊欄:
textInput("Id", "Label")
## <div class="form-group shiny-input-container">
## <label for="Id">Label</label>
## <input id="Id" type="text" class="form-control" value=""/>
## </div>
sidebarPanel(
div("First div"),
div("Second div")
)
## <div class="col-sm-4">
## <form class="well">
## <div>First div</div>
## <div>Second div</div>
## </form>
## </div>
Shiny app的UI構建這些HTML。shinydashboard包提供了一組函數用來創建HTML,將生成一個儀表板。如果你復制一個儀表板頁面的UI代碼(上圖)粘貼到R控制台,它將打印儀表板的HTML代碼。
3.1結構概述
儀表盤dashboardPage()函數三個組件:頭,側邊欄,身體:
dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody()
)
對於更復雜的APP,APP划分成塊可以讓它更可讀:
header <- dashboardHeader()
sidebar <- dashboardSidebar()
body <- dashboardBody()
dashboardPage(header, sidebar, body)
下面分別介紹上面的三個部分
3.2Header
標題可以有一個標題和下拉菜單,例子:
設置該標題比較簡單,僅需要使用title參數:
dashboardHeader(title = "My Dashboard")
dropdownMenu()函數生成下拉菜單。有三種類型的菜單——消息message、通知notification和任務tasks,每個菜單必須用相應類型的項填充。
3.2.1消息message菜單
在dropdownMenu()函數中添加messageItem()函數,messageItem()中包含消息菜單需要的值(from和message,form指的是消息來源,message指的是消息內容)。您還可以控制圖標和通知時間字符串。默認情況下,圖標是一個人的輪廓。(關於如何設置icon圖標,在后面的外觀中會有詳細的介紹)字符串可以是任何文本。例如,它可能是一個相對的日期/時間像“5分鍾”,“今天”,或“昨天中午12:30”,或者一個絕對時間,像“2014-12-01 13:45”。
dropdownMenu(type = "messages",
messageItem(
from = "Sales Dept",
message = "Sales are steady this month."
),
messageItem(
from = "New User",
message = "How do I register?",
icon = icon("question"),
time = "13:45"
),
messageItem(
from = "Support",
message = "The new server is ready.",
icon = icon("life-ring"),
time = "2014-12-01"
)
)
顯示動態內容
在大多數情況下,你會想要動態的內容。這意味着在服務器端生成HTML內容,發送到客戶端表現。在UI代碼,可以使用dropdownMenuOutput是這樣的:
dashboardHeader(dropdownMenuOutput("messageMenu"))
在服務器端,您在renderMenu中會生成整個菜單,如下:
output$messageMenu <- renderMenu({
# 此處生成每一個messageItems到list. This assumes
# 假設messageData是一個帶有兩列的數據框(data frame),兩列顯示的內容分別是'from' and 'message'.
msgs <- apply(messageData, 1, function(row) {
messageItem(from = row[["from"]], message = row[["message"]])
})
# 這相當於調用:
# dropdownMenu(type="messages", msgs[[1]], msgs[[2]], ...)
dropdownMenu(type = "messages", .list = msgs)
})
對於交互式的例子,使用幫助?renderMenu.
動態顯示sliderbarMenu:
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Dynamic sidebar"),
dashboardSidebar(
sidebarMenuOutput("menu")
),
dashboardBody()
)
server <- function(input, output) {
output$menu <- renderMenu({
sidebarMenu(
menuItem("Menu item", icon = icon("calendar"))
)
})
}
shinyApp(ui, server)
動態顯示dropdownMenu:
library(shiny)
library(shinydashboard)
# ========== Dynamic dropdownMenu ==========
# Example message data in a data frame
messageData <- data.frame(
from = c("Admininstrator", "New User", "Support"),
message = c(
"Sales are steady this month.",
"How do I register?",
"The new server is ready."
),
stringsAsFactors = FALSE
)
ui <- dashboardPage(
dashboardHeader(
title = "Dynamic menus",
dropdownMenuOutput("messageMenu")
),
dashboardSidebar(),
dashboardBody(
fluidRow(
box(
title = "Controls",
sliderInput("slider", "Number of observations:", 1, 100, 50)
)
)
)
)
server <- function(input, output) {
output$messageMenu <- renderMenu({
msgs <- apply(messageData, 1, function(row) {
messageItem(
from = row[["from"]],
message = paste(row[["message"]], input$slider)
)
})
dropdownMenu(type = "messages", .list = msgs)
})
}
shinyApp(ui, server)
下面是一個Shiny定制版本的動態UI,更多關於使用動態UI,看到這個例子:
UI.R
library(shiny)
shinyUI(fluidPage(
titlePanel("Dynamically generated user interface components"),
fluidRow(
column(3, wellPanel(
selectInput("input_type", "Input type",
c("slider", "text", "numeric", "checkbox",
"checkboxGroup", "radioButtons", "selectInput",
"selectInput (multi)", "date", "daterange"
)
)
)),
column(3, wellPanel(
# This outputs the dynamic UI component
uiOutput("ui")
)),
column(3,
tags$p("Input type:"),
verbatimTextOutput("input_type_text"),
tags$p("Dynamic input value:"),
verbatimTextOutput("dynamic_value")
)
)
))
server.R
library(shiny)
shinyServer(function(input, output) {
output$ui <- renderUI({
if (is.null(input$input_type))
return()
# Depending on input$input_type, we'll generate a different # UI component and send it to the client.
switch(input$input_type,
"slider" = sliderInput("dynamic", "Dynamic",
min = 1, max = 20, value = 10),
"text" = textInput("dynamic", "Dynamic",
value = "starting value"),
"numeric" = numericInput("dynamic", "Dynamic",
value = 12),
"checkbox" = checkboxInput("dynamic", "Dynamic",
value = TRUE),
"checkboxGroup" = checkboxGroupInput("dynamic", "Dynamic",
choices = c("Option 1" = "option1",
"Option 2" = "option2"),
selected = "option2"
),
"radioButtons" = radioButtons("dynamic", "Dynamic",
choices = c("Option 1" = "option1",
"Option 2" = "option2"),
selected = "option2"
),
"selectInput" = selectInput("dynamic", "Dynamic",
choices = c("Option 1" = "option1",
"Option 2" = "option2"),
selected = "option2"
),
"selectInput (multi)" = selectInput("dynamic", "Dynamic",
choices = c("Option 1" = "option1",
"Option 2" = "option2"),
selected = c("option1", "option2"),
multiple = TRUE
),
"date" = dateInput("dynamic", "Dynamic"),
"daterange" = dateRangeInput("dynamic", "Dynamic")
)
})
output$input_type_text <- renderText({
input$input_type
})
output$dynamic_value <- renderPrint({
str(input$dynamic)
})
})
顯示如下:
3.2.2通知notification
在dropdownMenu()函數中添加notificationItem()來包含一個文本通知。您還可以控制圖標和狀態的顏色。關於如何控制在后面會詳細介紹。
dropdownMenu(type = "notifications",
notificationItem(
text = "5 new users today",
icon("users")
),
notificationItem(
text = "12 items delivered",
icon("truck"),
status = "success"
),
notificationItem(
text = "Server load at 86%",
icon = icon("exclamation-triangle"),
status = "warning"
)
)
動態交互:
library(shiny)
library(shinydashboard)
# ========== Dynamic dropdownMenu ==========
# Example message data in a data frame
messageData <- data.frame(
text = c("5 new users today", "12 items delivered", "Server load at 86%"),
status = c(
"success",
"warning",
"warning"
),
stringsAsFactors = FALSE
)
ui <- dashboardPage(
dashboardHeader(
title = "Dynamic menus",
dropdownMenuOutput("notificationsMenu")
),
dashboardSidebar(),
dashboardBody(
fluidRow(
box(
title = "Controls",
sliderInput("slider", "Number of observations:", 1, 100, 50)
)
)
)
)
server <- function(input, output) {
output$notificationsMenu <- renderMenu({
msgs <- apply(messageData, 1, function(row) {
notificationItem(
text = row[["text"]],
status = row[["status"]]
)
})
dropdownMenu(type = "notifications", .list = msgs)
})
}
shinyApp(ui, server)
3.2.3任務tasks菜單
任務項有一個進度條和一個文本標簽。您還可以指定進度條的顏色,你可以使用? validColors列出可以有效的顏色。
red yellow aqua blue light-blue green navy teal olive lime orange fuchsia purple maroon black |
代碼如下:
dropdownMenu(type = "tasks", badgeStatus = "success",
taskItem(value = 90, color = "green",
"Documentation"
),
taskItem(value = 17, color = "aqua",
"Project X"
),
taskItem(value = 75, color = "yellow",
"Server deployment"
),
taskItem(value = 80, color = "red",
"Overall project"
)
)
3.2.4禁用標題頭
如果你不想顯示標題欄,您可以禁用它:
dashboardHeader(disable = TRUE)
3.3Sidebar
側邊欄通常用於快速導航,它包含像tabPanel標簽的菜單項,、以及shiny的輸入,如滑塊和文本輸入等,如下圖所示:
3.3.1側邊欄菜單項和選項卡
側邊欄中的鏈接可以像shiny中的tabPanels使用。也就是說,當你點擊一個鏈接,它將在儀表板的主體中顯示不同的內容。下面是一個tabPanel的簡單例子:
當用戶單擊其中一個菜單項,它轉換顯示在主體中的內容:
這些菜單項都放在sidebarMenu()方法中,如下所示。利用tabItem匹配一個menuItem,確保他們有可以匹配的tabName值。
## ui.R ##
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", icon = icon("th"), tabName = "widgets",
badgeLabel = "new", badgeColor = "green")
)
)
body <- dashboardBody(
tabItems(
tabItem(tabName = "dashboard",
h2("Dashboard tab content")
),
tabItem(tabName = "widgets",
h2("Widgets tab content")
)
)
)
# Put them together into a dashboardPage
dashboardPage(
dashboardHeader(title = "Simple tabs"),
sidebar,
body
)
menuItem有一個圖標icon選項, 由shiny的icon ()函數創建。(更多信息在后面會詳細介紹。)badgeLabel和badgeColor為選項標記,分別是表示名和標記顯示顏色。一個menuItem除了控制標簽可以做其他的事情;它還可以包含一個外部鏈接的內容,如果你為href提供一個值。默認情況下,這些外部鏈接打開一個新的瀏覽器標簽或窗口;這可以通過newtab選項達到效果。
menuItem("Source code", icon = icon("file-code-o"),
href = "https://github.com/rstudio/shinydashboard/")
下面為示例:
library(shiny)
library(shinydashboard)
# ========== Dynamic dropdownMenu ==========
# Example message data in a data frame
messageData <- data.frame(
text = c("5 new users today", "12 items delivered", "Server load at 86%"),
status = c(
"success",
"warning",
"warning"
),
stringsAsFactors = FALSE
)
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", icon = icon("th"), tabName = "widgets",
badgeLabel = "new", badgeColor = "green"),
menuItem("百度搜索", icon = icon("file-code-o"),
href = "http://www.baidu.com")
)
)
body <- dashboardBody(
tabItems(
tabItem(tabName = "dashboard",
h2("Dashboard tab content")
),
tabItem(tabName = "widgets",
h2("Widgets tab content")
)
)
)
ui <- dashboardPage(
dashboardHeader(
title = "Dynamic menus",
dropdownMenuOutput("notificationsMenu")
),
sidebar,
body
)
server <- function(input, output) {
output$notificationsMenu <- renderMenu({
msgs <- apply(messageData, 1, function(row) {
notificationItem(
text = row[["text"]],
status = row[["status"]]
)
})
dropdownMenu(type = "notifications", .list = msgs)
})
}
shinyApp(ui, server)
3.3.2動態內容
側邊欄菜單可以動態生成,renderMenu和sidebarMenuOutput。下面是一個示例應用程序與一個側邊欄,是在服務器端生成的。
ui <- dashboardPage(
dashboardHeader(title = "Dynamic sidebar"),
dashboardSidebar(
sidebarMenuOutput("menu")
),
dashboardBody()
)
server <- function(input, output) {
output$menu <- renderMenu({
sidebarMenu(
menuItem("Menu item", icon = icon("calendar"))
)
})
}
shinyApp(ui, server)
也可以動態生成個人物品:
ui <- dashboardPage(
dashboardHeader(title = "Dynamic sidebar"),
dashboardSidebar(
sidebarMenu(
menuItemOutput("menuitem")
)
),
dashboardBody()
)
server <- function(input, output) {
output$menuitem <- renderMenu({
menuItem("Menu item", icon = icon("calendar"))
})
}
shinyApp(ui, server)
3.3.3側邊欄加入輸入項
側邊欄也可以包含普通的輸入,如sliderInput和textInput:
shinydashboard還包括一個特殊類型的輸入,sidebarSearchForm,如上面的截圖所示,有一個搜索項。這本質上是一個特殊格式化的文本輸入和actionButton動作按鈕,它顯示為一個放大鏡圖標(圖標可以通過icon改變)。
sidebarSearchForm(textId = "searchText", buttonId = "searchButton",
label = "Search...")
對於這個搜索表單,相應的值在服務器端代碼輸入,分別是inputsearchText和inputsearchText和input searchButton。
library(shiny)
library(shinydashboard)
ui<-dashboardPage(
dashboardHeader(title = "Sidrbar inputs"),
dashboardSidebar(
sidebarSearchForm(textId = "searchText", buttonId = "searchButton",
label = "Search..."),
sliderInput("slider", "Slider:", 1, 100, 50),
textInput("text", "Text input:")
),
dashboardBody(
h2("鳶尾花數據集作圖")
)
)
server <- function(input, output){}
shinyApp(ui,server)
3.3.4隱藏側邊欄
dashboardSidebar(disable = TRUE)
3.4Body
儀表板頁面的主體可以包含任何常規的shiny內容。然而,如果你創建一個儀表板你可能會想要更加結構化的東西。大部分儀表板的基本構建塊是box。box反過來可以包含任何內容。
Boxes
boxes是主要的儀表板頁面的構建塊。box()函數可以創建一個基本的框,box的內容可以(大多數)是任何shiny的UI內容。
在一個典型的儀表板中,這些boxes將被放置在一個fluidRow()函數體中(稍后我們會看到更多關於儀表板布局介紹):
# This is just the body component of a dashboard
dashboardBody(
fluidRow(
box(plotOutput("plot1")),
box(
"Box content here", br(), "More box content",
sliderInput("slider", "Slider input:", 1, 100, 50),
textInput("text", "Text input:")
)
)
)
完整程序如下:
library(shiny)
library(shinydashboard)
ui<-dashboardPage(
dashboardHeader(title = "Sidrbar inputs"),
dashboardSidebar(
sidebarSearchForm(textId = "searchText", buttonId = "searchButton",
label = "Search..."),
sliderInput("slider", "Slider:", 1, 100, 50),
textInput("text", "Text input:")
),
dashboardBody(
fluidRow(
box(plotOutput("plot1")),
box(
"Box content here",br(),"More box content",
sliderInput("slider","Slider input:",1,100,50),
textInput("text","Text input:")
)
)
)
)
server <- function(input, output){
set.seed(122)
histdata <- rnorm(500)
output$plot1<-renderPlot({
hist(histdata)
})
}
shinyApp(ui,server)
boxes可以使用title和status設置標題和標題條顏色
box(title = "Histogram", status = "primary", plotOutput("plot1", height = 250)),
box(
title = "Inputs", status = "warning",
"Box content here", br(), "More box content",
sliderInput("slider", "Slider input:", 1, 100, 50),
textInput("text", "Text input:")
)
可以通過solidHeader = TRUE設置固體頭(長度一定的solid header),並通過collapsible=TRU在右上角顯示一個最小化按鈕(或者稱折疊按鈕)
box(
title = "Histogram", status = "primary", solidHeader = TRUE,
collapsible = TRUE,
plotOutput("plot1", height = 250)
),
box(
title = "Inputs", status = "warning", solidHeader = TRUE,
"Box content here", br(), "More box content",
sliderInput("slider", "Slider input:", 1, 100, 50),
textInput("text", "Text input:")
)
如果你想要boxes在頂部沒有灰色或彩色欄,使用solidHeader = TRUE,但不設置status參數,即可將上部分的灰色條或者彩色條去掉:
box(
title = "Histogram", solidHeader = TRUE,
collapsible = TRUE,
plotOutput("plot1", height = 250)
),
box(
title = "Inputs", solidHeader = TRUE,
"Box content here", br(), "More box content",
sliderInput("slider", "Slider input:", 1, 100, 50),
textInput("text", "Text input:")
)
最后,還可以使用background選項設置固定的背景:
box(
title = "Histogram", background = "maroon", solidHeader = TRUE,
plotOutput("plot1", height = 250)
),
box(
title = "Inputs", background = "black",
"Box content here", br(), "More box content",
sliderInput("slider", "Slider input:", 1, 100, 50),
textInput("text", "Text input:")
)