チュートリアルの目次はこちら。
このレッスンでは、Shinyアプリで使用するデータ、R スクリプト、およびパッケージをロードする方法を説明します。その過程で、米国国勢調査データを視覚化する洗練されたアプリを構築します。
counties.rds
counties.rds
は、UScensus2010
Rパッケージで収集された、米国の各郡の人口統計データのデータセットです。ここからダウンロードできます。
ファイルを入手したら、
census-app
ディレクトリ内に新しいdata
という名前のフォルダーを作成します。data
フォルダ内のcounties.rds
に移動します。
完了すると、census-app
フォルダーは次のようになります。
counties.rds
のデータセットは以下を含みます。
- 米国の各郡の名前
- 郡の総人口
- 郡内の住民のうち白人、黒人、ヒスパニック系、またはアジア人の割合
counties <- readRDS("census-app/data/counties.rds")
head(counties)
name total.pop white black hispanic asian
1 alabama,autauga 54571 77.2 19.3 2.4 0.9
2 alabama,baldwin 182265 83.5 10.9 4.4 0.7
3 alabama,barbour 27457 46.8 47.8 5.1 0.4
4 alabama,bibb 22915 75.0 22.9 1.8 0.1
5 alabama,blount 57322 88.9 2.5 8.1 0.2
6 alabama,bullock 10914 21.9 71.0 7.1 0.2
helpers.R
helpers.R
は、上の図のようなコロプレスマップの作成に役立つRスクリプトです。コロプレスマップは、色を使用して変数の地域的変動を表示するマップです。今回の場合、helpers.R
はcounties.rds
のデータをマップするように設計されたpercent_map
関数を作成します。ここからhelpers.R
をダウンロードできます。
helpers.R
では、maps
およびmapproj
パッケージを使用します。これらのパッケージをこれまでにインストールしたことがない場合は、このアプリを作成する前にインストールする必要があります。以下を実行します。
install.packages(c("maps", "mapproj"))
以下のように,census-app
ディレクトリ内にhelpers.Rを
保存します。
helpers.R
のpercent_map
関数は5つの引数を取ります。
Argument | Input |
var | countes.rds データセットの列ベクトル |
color | colors() の出力に表示される任意の文字列 |
legend.title | プロットの凡例のタイトルとして使用する文字列 |
max | シェード範囲を制御するためのパラメータ (デフォルトは 100) |
min | シェード範囲を制御するためのパラメータ (デフォルトは 0) |
コマンドラインでpercent_map
関数を使用すると、郡データをコロプレスマップとしてプロットできます。
library(maps)
library(mapproj)
source("census-app/helpers.R")
counties <- readRDS("census-app/data/counties.rds")
percent_map(counties$white, "darkgreen", "% White")
注: 上記のコードは、census-app
が作業ディレクトリ内のサブディレクトリであることを前提としています。作業ディレクトリをcensus-app
の親ディレクトリとして設定してください。作業ディレクトリの場所を変更するには、RStudioメニュー バーで「Session > Set Working Directory > Choose Directory」をクリックします。
percent_map
関数は郡データをコロプレスマップとしてプロットします。ここでは、郡内の白人住民の割合を濃い緑色でプロットします。
ファイルのロードとファイルパス
上記のコードを見てください。percent_map
関数を使用するには、まずsource
関数でhelpers.R
を走らせ、次にreadRDS
関数でcounties.rds
をロードします。library(maps), library(mapproj)
も実行します。
percent_map
関数をアプリで使用する前に、Shiny に同じ関数を呼び出すように要求する必要がありますが、これらの関数の記述方法は変わります。source
関数とreadRDS
関数の両方にファイルパスが必要ですが、ファイルパスはShinyアプリではコマンドラインでの場合と同じようには動作しません。
Shinyがserver.R
でコマンドを実行すると、すべてのファイルパスがserver.R
と同じディレクトリから始まるように処理されます。つまり、server.R
を保存したディレクトリがShinyアプリの作業ディレクトリになります。
server.R
と同じディレクトリにhelpers.R
を保存したので、Shinyに以下のようにロードするよう命令できます。
source("helpers.R")
server.R
があるディレクトリのサブディレクトリ(名前付きデータ)にcounties.rds
を保存したので、以下で読み込むことができます。
counties <- readRDS("data/counties.rds")
通常の方法で
とmap
mapproj
パッケージをロードできます。
library(maps)
library(mapproj)
ファイルパスは必要ありません。
実行
これらのコマンドを
スクリプトに配置すると、Shinyはこれらのコマンドをすべて実行します。ただし、スクリプトをどこに配置するかによって、スクリプトが実行 (または再実行) される回数が決まり、それがアプリのパフォーマンスに影響します。これは、Shinyがスクリプトの一部のセクションを他のセクションよりも頻繁に実行するためです。app.R
Shinyは、初めて
を呼び出したときにスクリプト全体を実行します。これにより、ShinyがrunApp
関数を実行します。server
Shinyは、新しいユーザーが到着するまで
関数を保存します。新しいユーザーがアプリにアクセスするたびに、Shinyはserver
関数を一回再実行します。この関数は、Shinyがユーザーごとに個別のリアクティブオブジェクトのセットを構築するのに役立ちます。server
ユーザーがウィジェットを操作してその値を変更すると、Shinyは、値が変更されたウィジェットに依存する各リアクティブオブジェクトに割り当てられた Rコードを再実行します。ユーザーが非常にアクティブである場合、これらの式は 1 秒間に何度も再実行される可能性があります。
これまでに学んだことは次のとおりです。
関数はアプリの起動時に1回実行されますshinyApp
関数は、ユーザーがアプリにアクセスするたびに1回実行されます。server
関数内のRコードは何度も実行されます。Shinyは、ユーザーがウィジェットの値を変更するたびに、それらを1回実行します。render*
この情報はどのように使用できるでしょうか?
の先頭,つまりapp.R
関数の外側において,スクリプトを読み込み、ライブラリをロードし、データ セットを読み込んでください。 Shinyはこのコードを1回だけ実行します。これだけで、 server
に含まれるRコードを実行するように設定できます。server
ユーザー固有のオブジェクトを
関数内で、かつserver
関数の外で定義します。これらは、各ユーザーが独自の個人用コピーを必要とすると考えられるオブジェクトです。たとえば、ユーザーのセッション情報を記録するオブジェクトです。このコードはユーザーごとに1回実行されます。render*
Shiny がオブジェクトを構築するために再実行する必要があるコードのみを
関数内に配置します。Shinyは、ユーザーがチャンク内でのウィジェットを変更するたびに、render*
チャンク内のすべてのコードを再実行します。これは非常に頻繁に起こります。render*
一般に、必要のないコードを
関数内に配置することは避けてください。そうすると、アプリ全体の速度が低下します。render*
Your turn 1
次の
ファイルをコピーしてapp.R
ディレクトリに貼り付けます。census-app
そして以下を
ファイルに加えます。app.R
source("helpers.R")
counties <- readRDS("data/counties.rds")
library(maps)
library(mapproj)
コマンドは効率的な場所に配置してください。
注: これは、アプリを完成させる2つの手順のうちの最初の手順です。上記のコードを挿入する最適な場所を選択してください。ただし、アプリを実行しないでください。2つ目のステップ (Your turn 2) で実際のコードに
部分を置き換えるまで、アプリはエラーを返します。#some arguments
ui.R
# User interface ----
ui <- page_sidebar(
title = "censusVis",
sidebar = sidebar(
helpText(
"Create demographic maps with information from the 2010 US Census."
),
selectInput(
"var",
label = "Choose a variable to display",
choices =
c(
"Percent White",
"Percent Black",
"Percent Hispanic",
"Percent Asian"
),
selected = "Percent White"
),
sliderInput(
"range",
label = "Range of interest:",
min = 0,
max = 100,
value = c(0, 100)
)
),
card(plotOutput("map"))
)
# Server logic ----
server <- function(input, output) {
output$map <- renderPlot({
percent_map( # some arguments )
})
}
# Run app ----
shinyApp(ui, server)
模範解答1
アプリは
とhelpers.R
を1回読み込むだけでよいため、counties.rds
とui
関数の外に置く必要があります。これは、server
ライブラリ (map
関数に使用する)をロードするのにも適した場所です。percent_map
library(maps)
library(mapproj)
source("helpers.R")
counties <- readRDS("data/counties.rds")
# User interface ----
ui <- page_sidebar(
title = "censusVis",
sidebar = sidebar(
helpText(
"Create demographic maps with information from the 2010 US Census."
),
selectInput(
"var",
label = "Choose a variable to display",
choices =
c(
"Percent White",
"Percent Black",
"Percent Hispanic",
"Percent Asian"
),
selected = "Percent White"
),
sliderInput(
"range",
label = "Range of interest:",
min = 0,
max = 100,
value = c(0, 100)
),
),
card(plotOutput("map"))
)
# Server logic ----
server <- function(input, output) {
output$map <- renderPlot({
percent_map( # some arguments )
})
}
# Run app ----
shinyApp(ui, server)
「各ユーザーがcounties
とpercent_map
の独自のコピーを必要とするのではないか?」と疑問に思うかもしれません。 (これは、コードがserver
関数の内部に入る必要があることを意味します)。いいえ、各ユーザーはそうではありません。
ユーザーのコンピューターでは ShinyアプリのRコードは実行されないことに注意してください。実際、彼らのコンピュータはRコードさえ認識しません。サーバーとして使用するコンピューターは、すべてのユーザーに必要なすべてのRコードを実行します。結果は HTML要素としてユーザーに送信されます。
サーバーは、 counties.rds
とpercent_map
の単一のグローバルコピーに依存してすべてのユーザーに必要なRコードをすべて実行できます。オブジェクトの値がユーザーごとに異なる場合にのみ、ユーザーごとに個別のオブジェクトを構築する必要があります。
アプリを終了する
国勢調査視覚化アプリには、 "map"
という名前のプロットである1つのリアクティブオブジェクトがあります。プロットは5つの引数を取るpercent_map
関数を使用して構築されます。
- 最初の 3 つの引数
var
、color
、および はlegend.title
は,選択ボックスウィジェットの値によって異なります。 - 最後の2つの引数
max
とmin
は、スライダーバーウィジェットの最大値と最小値に対応します。
以下のserver
関数は、percent_map
関数のリアクティブな引数を作成する1つの方法を示しています。 Rのswitch
関数は、セレクトボックスウィジェットの値を任意のものに変換できます。ただし、スクリプトは不完全です。color、legend.title、max、またはminの値は定義されていません。注: スクリプトはそのままでは実行されません。スクリプトを実行する前にスクリプトを完成させる必要があります。これがYour turn 2のタスクです。
server <- function(input, output) {
output$map <- renderPlot({
data <- switch(input$var,
"Percent White" = counties$white,
"Percent Black" = counties$black,
"Percent Hispanic" = counties$hispanic,
"Percent Asian" = counties$asian)
percent_map(var = data, color = ?, legend.title = ?, max = ?, min = ?)
})
}
Your turn 2
コードを完成させて、きちんと動く国勢調査視覚化アプリを構築します。
アプリをデプロイする準備ができたら、app.R
ファイルを保存してrunApp("census-app")
を実行します。すべてが機能すると、アプリは下の図のようになります。
以下はあなたが決める必要があります
percent_map
関数の引数の値を作成する方法、- これらの引数を作成するコードをどこに置くか
ユーザーが関連するウィジェットを変更するたびに引数の値を切り替える必要があることに注意してください。完了した場合、または行き詰まった場合は、以下の模範解答を読んでください。
模範解答2
# Load packages ----
library(shiny)
library(maps)
library(mapproj)
# Load data ----
counties <- readRDS("data/counties.rds")
# Source helper functions -----
source("helpers.R")
# User interface ----
ui <- page_sidebar(
title = "censusVis",
sidebar = sidebar(
helpText(
"Create demographic maps with information from the 2010 US Census."
),
selectInput(
"var",
label = "Choose a variable to display",
choices =
c(
"Percent White",
"Percent Black",
"Percent Hispanic",
"Percent Asian"
),
selected = "Percent White"
),
sliderInput(
"range",
label = "Range of interest:",
min = 0,
max = 100,
value = c(0, 100)
)
),
card(plotOutput("map"))
)
# Server logic ----
server <- function(input, output) {
output$map <- renderPlot({
data <- switch(input$var,
"Percent White" = counties$white,
"Percent Black" = counties$black,
"Percent Hispanic" = counties$hispanic,
"Percent Asian" = counties$asian)
color <- switch(input$var,
"Percent White" = "darkgreen",
"Percent Black" = "black",
"Percent Hispanic" = "darkorange",
"Percent Asian" = "darkviolet")
legend <- switch(input$var,
"Percent White" = "% White",
"Percent Black" = "% Black",
"Percent Hispanic" = "% Hispanic",
"Percent Asian" = "% Asian")
percent_map(data, color, legend, input$range[1], input$range[2])
})
}
# Run app ----
shinyApp(ui, server)
server
関数のより簡潔なバージョンは次のとおりです。
server <- function(input, output) {
output$map <- renderPlot({
args <- switch(input$var,
"Percent White" = list(counties$white, "darkgreen", "% White"),
"Percent Black" = list(counties$black, "black", "% Black"),
"Percent Hispanic" = list(counties$hispanic, "darkorange", "% Hispanic"),
"Percent Asian" = list(counties$asian, "darkviolet", "% Asian"))
args$min <- input$range[1]
args$max <- input$range[2]
do.call(percent_map, args)
})
}
要約
R スクリプト、パッケージ、データ セットを読み込むことで、より複雑なShinyアプリを作成できます。
以下の点に留意してください:
app.R
のあるディレクトリがShinyアプリの作業ディレクトリになります。- Shiny は、
app.R
の最初、つまりserver
関数の前に配置されたコードを、アプリの動作中に1回だけ実行します。 - Shinyは
server
関数内に配置されたコードを複数回実行するため、これによりアプリの速度が低下する可能性があります。
また、switch
関数が複数選択のShinyウィジェットを使用する際に便利なことも学びました。ウィジェットの値をRの中で変更するためにswitch
関数を使用します。
アプリが複雑になると、非効率的で遅くなる可能性があります。レッスン 6では、リアクティブな表現を使用して高速なモジュール型アプリを構築する方法を説明します。
コメント