diff --git a/public/2024-06-delta/search.json b/public/2024-06-delta/search.json index c97fbfac..b41b952d 100644 --- a/public/2024-06-delta/search.json +++ b/public/2024-06-delta/search.json @@ -1334,7 +1334,7 @@ "href": "session_15.html#the-anatomy-of-a-shiny-app", "title": "15  Introduction to Shiny", "section": "15.2 The Anatomy of a Shiny App", - "text": "15.2 The Anatomy of a Shiny App\n\n15.2.1 Building blocks\nShiny apps are composed in two parts:\n\nA web page that displays the app to a user (i.e. the user interface, or UI for short - frontend), and\nA computer that powers the app (i.e. the server - backend)\n\n\n\n\nSource: Intro to Shiny - Building reactive apps and dashboards, MEDS, UCSB\n\n\n\nThe UI controls the layout and appearance of your app and is written in HTML (but we use functions from the {shiny} package to write that HTML). The server handles the logic of the app – in other words, it is a set of instructions that tells the web page what to display when a user interacts with it.\nLet’s take a look at how the code for a very simple Shiny app would look like to get a sense of the fundamental architecture of this tool.\n\nlibrary(shiny)\n\n# Define the UI\n1ui <- shiny::fluidPage(\n \"Hello there!\"\n)\n\n# Define the server\n2server <- function(input, output){ }\n\n# Generate the app\nshiny::shinyApp(ui = ui, server = server)\n\n\n1\n\nThe fluidPage is a function that generates a page. It is important for allowing flexibility in UI layout which we’ll dive deeper later.\n\n2\n\nThe server is actually a function with input and output as arguments. , where you’ll add all the code related to the computations.Because this app has no inputs or outputs, it doesn’t need anything in the ‘server’ component (though it still does require an “empty server”)\n\n\n\n\nIf we run the code above, we should see an app that is a blank white page with “Hello there!” written in the top left in plain text.\n\nWith this code we have essentially built a Shiny app. More complicated apps will certainly have more content in the UI and server sections but all Shiny apps will have this tripartite structure (Define UI, Define the Server and Generate the app).\n\n\n15.2.2 What will go in each section?\n\n\n\nSection\nComponent\n\n\n\n\nUI\n\nInputs - or widgets ways the user can interact with (e.g. toggle, slide) and provide values to your app.\nOutputs - The R objects that your user sees (e.g. tables, plots). Outputs respond when a user interacts with or changes an input value.\nLayout - how the different components of the app are arranged.\nTheme - defines the overall appearance of your app.\n\n\n\nServer\n\nComputations - code that will create the outputs displayed in your app (values, tables, plots, etc).\n\n\n\n\nToday we are going to focus on understanding how the inputs and outputs work on the UI and how the sever operates to react based on inputs and display the outputs.\n\n\n\n15.2.3 More on widgets and outputs\n\nWidgets are web elements that users can interact with via the UI.\n\nWidgets collect information from the user which is then used to update outputs created in the server. Shiny provides a set of standard widgets (see image below), but you can also explore widget extensions using a variety of other packages (e.g. {shinyWidgets}, {DT}, {plotly}) \n\n\nOutputs are R objects you will display on your app. This can be plots, tables, values, or others. Generally, these outputs are going to react to as the user interact with the inputs.\nExample of input widgets and an output plot.\n\n\n\nSource: Intro to Shiny - Building reactive apps and dashboards, MEDS, UCSB\n\n\n\n\n15.2.4 Reactivity: brief intro\nReactivity is what makes Shiny apps responsive i.e. it lets the app instantly update itself whenever the user makes a change. At a very basic level, it looks something like this:\n\n\n\nSource: Intro to Shiny - Building reactive apps and dashboards, MEDS, UCSB\n\n\n\n\n\n\n\n\nHow to understand reactivity?\n\n\n\nCheck out Garrett Grolemund’s article, How to understand reactivity in R for a more detailed overview of Shiny reactivity.", + "text": "15.2 The Anatomy of a Shiny App\n\n15.2.1 Building blocks\nShiny apps are composed in two parts:\n\nA web page that displays the app to a user (i.e. the user interface, or UI for short - frontend), and\nA computer that powers the app (i.e. the server - backend)\n\n\n\n\nSource: Intro to Shiny - Building reactive apps and dashboards, MEDS, UCSB\n\n\n\nThe UI controls the layout and appearance of your app and is written in HTML (but we use functions from the {shiny} package to write that HTML). The server handles the logic of the app – in other words, it is a set of instructions that tells the web page what to display when a user interacts with it.\nLet’s take a look at how the code for a very simple Shiny app would look like to get a sense of the fundamental architecture of this tool.\n\nlibrary(shiny)\n\n# Define the UI\n1ui <- shiny::fluidPage(\n \"Hello there!\"\n)\n\n# Define the server\n2server <- function(input, output){ }\n\n# Generate the app\nshiny::shinyApp(ui = ui, server = server)\n\n\n1\n\nThe fluidPage is a function that generates a page. It is important for allowing flexibility in UI layout which we’ll dive deeper later.\n\n2\n\nThe server is actually a function with input and output as arguments. , where you’ll add all the code related to the computations.Because this app has no inputs or outputs, it doesn’t need anything in the ‘server’ component (though it still does require an “empty server”)\n\n\n\n\nIf we run the code above, we should see an app that is a blank white page with “Hello there!” written in the top left in plain text.\n\nWith this code we have essentially built a Shiny app. More complicated apps will certainly have more content in the UI and server sections but all Shiny apps will have this tripartite structure (Define UI, Define the Server and Generate the app).\n\n\n15.2.2 What will go in each section?\n\n\n\nSection\nComponent\n\n\n\n\nUI\n\nInputs - or widgets ways the user can interact with (e.g. toggle, slide) and provide values to your app.\nOutputs - The R objects that your user sees (e.g. tables, plots). Outputs respond when a user interacts with or changes an input value.\nLayout - how the different components of the app are arranged.\nTheme - defines the overall appearance of your app.\n\n\n\nServer\n\nComputations - code that will create the outputs displayed in your app (values, tables, plots, etc).\n\n\n\n\nWe are going to begin by focusing on understanding how the inputs and outputs work on the UI and how the sever operates to react based on inputs and display the outputs.\n\n\n\n15.2.3 More on widgets and outputs\n\nWidgets are web elements that users can interact with via the UI.\n\nWidgets collect information from the user which is then used to update outputs created in the server. Shiny provides a set of standard widgets (see image below), but you can also explore widget extensions using a variety of other packages (e.g. {shinyWidgets}, {DT}, {plotly}) \n\n\nOutputs are R objects you will display on your app. This can be plots, tables, values, or others. Generally, these outputs are going to react to as the user interact with the inputs.\nExample of input widgets and an output plot.\n\n\n\nSource: Intro to Shiny - Building reactive apps and dashboards, MEDS, UCSB\n\n\n\n\n15.2.4 Reactivity: brief intro\nReactivity is what makes Shiny apps responsive i.e. it lets the app instantly update itself whenever the user makes a change. At a very basic level, it looks something like this:\n\n\n\nSource: Intro to Shiny - Building reactive apps and dashboards, MEDS, UCSB\n\n\n\n\n\n\n\n\nHow to understand reactivity?\n\n\n\nCheck out Garrett Grolemund’s article, How to understand reactivity in R for a more detailed overview of Shiny reactivity.", "crumbs": [ "15  Introduction to Shiny" ] @@ -1354,17 +1354,17 @@ "href": "session_15.html#creating-a-shiny-app", "title": "15  Introduction to Shiny", "section": "15.4 Creating a Shiny app", - "text": "15.4 Creating a Shiny app\n\n\n\n\n\n\nSet up: Create GitHub Repo\n\n\n\n\nCreate a repo to house our soon-to-be app(s). Navigate to your GitHub account, go to Your repositories > Click on New repository. Named it shiny-app-example Remember to initiate your repo with a README and choose R as the language for the default .gitignore.\nClone your repo into your RStudio Session in the server. Click on the green “< >Code” button > Copy the HTTPS url and then go to RStudio\nIn RStudio Create a new project. Go to File > New Project > Version Control with Git > paste Repository url > Create Project\n\nThe GIF bellow shows each of these steps as a visual reference. Thank you Sam Csik, who created this great resource!\n\n\n\n\n\n\n\n\nYou can create a single-file app using RStudio’s built-in Shiny app template (e.g. File > New Project > New Directory > Shiny Application), but it’s just as easy to create it from scratch (and you’ll memorize the structure faster!). Let’s do that now.\n\n\n\n\n\n\n\nSet up: Your first Shiny app\n\n\n\n\nIn your project repo, create a sub-directory to house your app. Name it single-file-app.\nCreate a new R script inside single-file-app/ and name it app.R – you must name your script app.R.\nCopy or type the following code into app.R, or use the shinyapp snippet to automatically generate a shiny app template.\n\n\n# load packages ----\nlibrary(shiny)\n\n# user interface ----\nui <- fluidPage()\n\n# server instructions ----\nserver <- function(input, output) {}\n\n# combine UI & server into an app ----\nshinyApp(ui = ui, server = server)\n\nTip: Use code sections (denoted by # some text ----) to make navigating different sections of your app code a bit easier. Code sections will appear in your document Outline (find the button at the top right corner of the script/editor panel).\n\n\nOnce you have saved your app.R file, the “Run” code button should turn into a “Run App” button. Click that button to run your app (alternatively, run runApp(\"directory-name\") in your console.\n\nrunApp(\"single-file-app\")\n\nYou won’t see much yet, as we have only built a blank app (but a functioning app, nonetheless!).\nYou should also notice a red stop sign appear in the top right corner of your console indicating that R is busy – this is because your R session is currently acting as your Shiny app server and listening for any user interaction with your app. Because of this, you won’t be able to run any commands in the console until you quit your app. To quit the app you have to press the stop button.\n\n15.4.1 Building a single-file-app\nWe are now going to add elements to our base app. We will use data from {palmerpenguin} package and add the following features to our app:\n\nA title and subtitle\nA slider widget for users to select a range of penguin body masses\nA reactive scatterplot that updates based on user-supplied values\n\n\n\n\n\nSource: Intro to Shiny - Building reactive apps and dashboards, MEDS, UCSB\n\n\n\n\n\n\n\n\n\nAbout {palmerpenguin}\n\n\n\nThe palmerpenguins data contains size measurements for three penguin species (Chinstrap, Gentoo and Adelie) observed on three islands in the Palmer Archipelago, Antarctica (Torgersen, Biscoe, and Dream).\n\n\n\n\n15.4.2 Adding text to the UI: Title and Subtitle\nWe will do this in the UI withing fluidPage(). Remember this is a layout function that creates the basic visual structure of your app page.\nLet’s add a title and subtitle to our app. Make sure they are separated with a coma!\n\n# user interface ----\nui <- fluidPage(\n \n # app title ----\n \"My App Title\",\n \n # app subtitle ----\n \"Exploring Antarctic Penguin Data\"\n \n )\n\n\n\n15.4.3 Style text in the UI\nThe UI is actually an HTML document. We can style our text by adding static HTML elements using tags – a list of functions that parallel common HTML tags (e.g. <h1> == tags$h1()) The most common tags also have wrapper functions (e.g. h1()).\n\n# user interface ----\nui <- fluidPage(\n \n # app title ----\n tags$h1(\"My App Title\"), # alternatively, you can use the `h1()` wrapper function\n \n # app subtitle ----\n h4(strong(\"Exploring Antarctic Penguin Data\")) # alternatively, `tags$h4(tags$strong(\"text\"))`\n \n )\n\n\n\nAdding intupts and outputs\nNext, we will begin to add some inputs and outputs to our UI inside fluidPage(). Anything that you put into fluidPage() will appear in our app’s user interface. We want inputs and outputs to show up there.\n\nStep 1: add an input to your app (slider widget)\n\n# user interface ----\nui <- fluidPage(\n \n # app title ----\n tags$h1(\"My App Title\"), # alternatively, you can use the `h1()` wrapper function\n \n # app subtitle ----\n h4(strong(\"Exploring Antarctic Penguin Data\")), # alternatively, `tags$h4(tags$strong(\"text\"))`\n \n # body mass slider input ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000))\n \n )\n\n\n\nStep 2: add an output “placeholder” in the UI\nOutputs in the UI create placeholders which are later filled by the server function.\nSimilar to input functions, all output functions take the same first argument, outputId (note Id not ID), which connects the front end UI with the back end server. For example, if your UI contains an output function with an outputId = \"plot\", the server function will access it (or in other words, know to place the plot in that particular placeholder) using the syntax output$plot. \n\n# user interface ----\nui <- fluidPage(\n \n # app title ----\n tags$h1(\"My App Title\"), # alternatively, you can use the `h1()` wrapper function\n \n # app subtitle ----\n h4(strong(\"Exploring Antarctic Penguin Data\")), # alternatively, `tags$h4(tags$strong(\"text\"))`\n \n # body mass slider input ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000)),\n \n # body mass plot ouput ----\n plotOutput(outputId = \"bodyMass_scatterplot_output\")\n \n )\n\nOkay, it looks like nothing changed?? Remember, *Output() functions create placeholders, but we have not yet written the server instructions on how to fill and update those placeholders. We can inspect the HTML and see that there is, in fact, a placeholder area awaiting our eventual output, which will be a plot named “bodyMass_scatterplot_output”:\n\n\n\nSource: Intro to Shiny - Building reactive apps and dashboards, MEDS, UCSB\n\n\n\n\n\n\nTell the server how to assemble inputs into outputs: Adding reactive scatterplot\nNow that we’ve designed our input / output in the UI, we need to write the server instructions (i.e. write the server function) on how to use the input value(s) (i.e. penguin body mass range via a slider input) to update the output (scatter plot).\nThe server function is defined with two arguments, input and output, both of which are list-like objects. You must define both of these arguments within the server function. input contains the values of all the different inputs at any given time, while output is where you’ll save output objects to be displayed in the app.\nRULES\n\nSave objects you want to display to output$<id>\nBuild reactive objects using a render*() function\nAccess input values with input$\n\n\nRule 1: Save objects you want to display to output$<id>\n\n# load packages ----\nlibrary(shiny)\n\n# user interface ----\nui <- fluidPage(\n \n # ~ previous code omitted for brevity ~\n \n # body mass slider ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000)),\n \n # body mass plot output ----\n plotOutput(outputId = \"bodyMass_scatterplot_output\") \n \n)\n\n# server instructions ----\nserver <- function(input, output) {\n \n # render penguin scatter plot ----\n output$bodyMass_scatterplot_output <- # code to generate plot here\n \n}\n\nNote: In the UI, our outputId is quoted (“bodyMass_scatterplot_output”), but not in the server (bodyMass_scatterplot_output).\n\n\nRule 2: Build reactive objects with render*()\nEach *Output() function in the UI is coupled with a render*() function in the server, which contains the “instructions” for creating the output based on user inputs (or in other words, the instructions for making your output reactive).\n\n\n\n\nOutput function\nRender function\n\n\n\n\ndataTableOutput()\nrenderDataTable()\n\n\nimageOutput()\nrenderImage()\n\n\nplotOutput()\nrenderPlot()\n\n\ntableOutput()\nrenderTable()\n\n\ntextOutput()\nrenderText()\n\n\n\n\n\n# load packages ----\nlibrary(shiny)\n\n# user interface ----\nui <- fluidPage(\n \n # ~ previous code omitted for brevity ~\n \n # body mass slider ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000)),\n \n # body mass plot output ----\n plotOutput(outputId = \"bodyMass_scatterplot_output\") \n \n)\n\n# server instructions ----\nserver <- function(input, output) {\n \n # render penguin scatter plot ----\n output$bodyMass_scatterplot_output <- renderPlot({\n \n # code to generate plot here\n \n }) \n}\n\n\n\n\n\n\n\n\nAside: Write the code for the output objects in separate script first\n\n\n\nIt is generally easier to experiment with the R objects you wan to show in your app (e.g. plots) in a separate script first and then copy the code over to your app. For example, if we want to make a scatter plot showing the relationship between flipper length and bill length for the different penguin species on palmerpenguins we would start by opening a new R script and write the code for this plot.\nIn RStudio, go to File > New File > RScript. Save this file as practice-script.R into the scratch folder. Now let’s copy and paste the code below. This code creates our scatter plot.\n\n# load packages ----\nlibrary(palmerpenguins)\nlibrary(ggplot2)\n\n# create scatterplot ----\nggplot(na.omit(penguins), \n aes(x = flipper_length_mm, y = bill_length_mm, \n color = species, shape = species)) +\n geom_point() +\n scale_color_manual(values = c(\"Adelie\" = \"darkorange\", \"Chinstrap\" = \"purple\", \"Gentoo\" = \"cyan4\")) +\n scale_shape_manual(values = c(\"Adelie\" = 19, \"Chinstrap\" = 17, \"Gentoo\" = 15)) +\n labs(x = \"Flipper length (mm)\", y = \"Bill length (mm)\", \n color = \"Penguin species\", shape = \"Penguin species\") +\n theme_minimal() +\n theme(legend.position = c(0.85, 0.2),\n legend.background = element_rect(color = \"white\"))\n\n\n\n\n\n\n\n\n\n\nNext, copy your plot code into the server\nCopy your code over to your app, placing it inside the {} (and make sure to add any additional required packages to the top of your app.R script). Run your app. What do you notice?\n\n# load packages ----\nlibrary(shiny)\nlibrary(palmerpenguins)\nlibrary(tidyverse)\n\n# user interface ----\nui <- fluidPage(\n \n # ~ previous code omitted for brevity ~\n \n # body mass slider ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000)),\n \n # body mass plot output ----\n plotOutput(outputId = \"bodyMass_scatterplot_output\")\n \n)\n\n# server instructions ----\nserver <- function(input, output) {\n \n # render penguin scatter plot ----\n output$bodyMass_scatterplot_output <- renderPlot({ \n ggplot(na.omit(penguins),\n aes(x = flipper_length_mm, y = bill_length_mm,\n color = species, shape = species)) + \n geom_point() + \n scale_color_manual(values = c(\"Adelie\" = \"#FEA346\", \"Chinstrap\" = \"#B251F1\", \"Gentoo\" = \"#4BA4A4\")) +\n scale_shape_manual(values = c(\"Adelie\" = 19, \"Chinstrap\" = 17, \"Gentoo\" = 15)) +\n labs(x = \"Flipper length (mm)\", y = \"Bill length (mm)\", \n color = \"Penguin species\", shape = \"Penguin species\") + \n theme_minimal() + \n theme(legend.position = c(0.85, 0.2), \n legend.background = element_rect(color = \"white\")) \n })\n}\n\n\n\n\n\nGreat! We have plot! But… It is not reactive. We have not yet told the server how to update the plot based on user inputs via the sliderInput() in the UI. Let’s do that next.\n\n\n\n\n\n\n\nAside: Practice filtering data in a separate script\n\n\n\nGo back to out practice script practice-script.R and create a new data frame where we filter the body_mass_g column for observations within a specific range of values (in this example, values ranging from 3000 - 4000).\n\n# filter penguins df for observations where body_mass_g >= 3000 & <= 4000 ----\nbody_mass_df <- penguins %>% \n filter(body_mass_g %in% c(3000:4000))\n\nThen, plot the new filtered data frame.\n\n# plot new, filtered data ----\nggplot(na.omit(body_mass_df), # plot 'body_mass_df' rather than 'penguins' df\n aes(x = flipper_length_mm, y = bill_length_mm, \n color = species, shape = species)) +\n geom_point() +\n scale_color_manual(values = c(\"Adelie\" = \"#FEA346\", \"Chinstrap\" = \"#B251F1\", \"Gentoo\" = \"#4BA4A4\")) +\n scale_shape_manual(values = c(\"Adelie\" = 19, \"Chinstrap\" = 17, \"Gentoo\" = 15)) +\n labs(x = \"Flipper length (mm)\", y = \"Bill length (mm)\", \n color = \"Penguin species\", shape = \"Penguin species\") +\n theme_minimal() +\n theme(legend.position = c(0.85, 0.2),\n legend.background = element_rect(color = \"white\"))\n\n\n\n\nWhich part of our code needs to be updated when a user changes the slider range input?\nFor example if someone inputs the following range:\n\n\n\n\n\nThe code has to do something like this.\n\nbody_mass_df <- penguins %>% \n filter(body_mass_g %in% c(2857:5903))\n\n\n\n\nRule 3: Access input values with input$<id>\nRemember that in our UI we we gave the slidrInput() an inputID = body_mass_input.\n\n# body mass slider ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\", \n min = 2700, max = 6300, value = c(3000, 4000))\n\nNow we need to add the input piece on the server side. We can access the values of that slider input in the server using the syntax, input$body_mass_input. If you want your output to change according to the input values, substitute hard-coded values (e.g. 2857:5903) with the input values from the UI. For example, c(input$body_mass_input[1]:input$body_mass_input[2]\n\n\n\n\n\n\n\nReactive Data Frame\n\n\n\nWe need to create a reactive data frame that is able to update according to the input. For this we use the reactive() function.\nWhen you call your reactive data frame in your ggplot, the data frame name must be followed by ()\n\n\n\n\n# load packages ----\nlibrary(shiny)\nlibrary(palmerpenguins)\nlibrary(tidyverse)\n\n# user interface ----\nui <- fluidPage(\n \n # ~ previous code omitted for brevity ~\n \n # body mass slider ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000)),\n \n # body mass plot output ----\n plotOutput(outputId = \"bodyMass_scatterplot_output\")\n \n)\n\n# server instructions ----\nserver <- function(input, output) {\n \n # filter body masses ----\n body_mass_df <- reactive({ \n penguins %>% \n filter(body_mass_g %in% c(input$body_mass_input[1]:input$body_mass_input[2])) \n })\n \n # render penguin scatter plot ----\n output$bodyMass_scatterplot_output <- renderPlot({ \n ggplot(na.omit(body_mass_df()),\n aes(x = flipper_length_mm, y = bill_length_mm,\n color = species, shape = species)) + \n geom_point() + \n scale_color_manual(values = c(\"Adelie\" = \"#FEA346\", \"Chinstrap\" = \"#B251F1\", \"Gentoo\" = \"#4BA4A4\")) +\n scale_shape_manual(values = c(\"Adelie\" = 19, \"Chinstrap\" = 17, \"Gentoo\" = 15)) +\n labs(x = \"Flipper length (mm)\", y = \"Bill length (mm)\", \n color = \"Penguin species\", shape = \"Penguin species\") + \n theme_minimal() + \n theme(legend.position = c(0.85, 0.2), \n legend.background = element_rect(color = \"white\")) \n })\n}\n\nNow let’s tun the app! We should now see a reactive Shiny app. Note that reactivity automatically occurs whenever you use an input value to render an output object.\n\n\n\n15.4.4 Recap: Steps to create a reactive Shiny app\n\nWe created an app.R file in it’s own directory and began our app with the template, though you can also create a two-file Shiny app by using separate ui.R and server.R files.\nWe added an input to the fluidPage() in our UI using an *Input() function and gave it a unique inputId (e.g. inputId = \"unique_input_Id_name\")\nWe created a placeholder for our reactive object by using an *Output() function in the fluidPage() of our UI and gave it an outputId (e.g. outputId = \"output_Id_name\")\nWe wrote the server instructions for how to assemble inputs into outputs, following these rules:\n\n\nSave objects that you want to display to output$<id>\nBuild reactive objects using a render*() function (and similarly, build reactive data frames using reactive() )\nAccess input values with input$<id>\n\nAnd… we saw that reactivity automatically occurs whenever we use an input value to render an output object.", + "text": "15.4 Creating a Shiny app\n\n\n\n\n\n\nSet up: Create GitHub Repo\n\n\n\n\nCreate a repo to house our soon-to-be app(s). Navigate to your GitHub account, go to Your repositories > Click on New repository. Named it shiny-app-example Remember to initiate your repo with a README and choose R as the language for the default .gitignore.\nClone your repo into your RStudio Session in the server. Click on the green “< >Code” button > Copy the HTTPS url and then go to RStudio\nIn RStudio Create a new project. Go to File > New Project > Version Control with Git > paste Repository url > Create Project\n\nThe GIF bellow shows each of these steps as a visual reference. Thank you Sam Csik, who created this great resource!\n\n\n\n\n\n\n\n\nYou can create a single-file app using RStudio’s built-in Shiny app template (e.g. File > New Project > New Directory > Shiny Application), but it’s just as easy to create it from scratch (and you’ll memorize the structure faster!). Let’s do that now.\n\n\n\n\n\n\n\nSet up: Your first Shiny app\n\n\n\n\nIn your project repo, create a sub-directory to house your app. Name it single-file-app. And a dub-directory for all our scratch code (e.g practice plots or subset df.)\nCreate a new R script inside single-file-app/ and name it app.R – you must name your script app.R.\nCopy or type the following code into app.R, or use the shinyapp snippet to automatically generate a shiny app template.\n\n\n# load packages ----\nlibrary(shiny)\n\n# user interface ----\nui <- fluidPage()\n\n# server instructions ----\nserver <- function(input, output) {}\n\n# combine UI & server into an app ----\nshinyApp(ui = ui, server = server)\n\nTip: Use code sections (denoted by # some text ----) to make navigating different sections of your app code a bit easier. Code sections will appear in your document Outline (find the button at the top right corner of the script/editor panel).\n\n\nOnce you have saved your app.R file, the “Run” code button should turn into a “Run App” button. Click that button to run your app (alternatively, run runApp(\"directory-name\") in your console.\n\nrunApp(\"single-file-app\")\n\nYou won’t see much yet, as we have only built a blank app (but a functioning app, nonetheless!).\nYou should also notice a red stop sign appear in the top right corner of your console indicating that R is busy – this is because your R session is currently acting as your Shiny app server and listening for any user interaction with your app. Because of this, you won’t be able to run any commands in the console until you quit your app. To quit the app you have to press the stop button.\n\n15.4.1 Building a single-file-app\nWe are now going to add elements to our base app. We will use data from {palmerpenguin} package and add the following features to our app:\n\nA title and subtitle\nA slider widget for users to select a range of penguin body masses\nA reactive scatterplot that updates based on user-supplied values\n\n\n\n\n\nSource: Intro to Shiny - Building reactive apps and dashboards, MEDS, UCSB\n\n\n\n\n\n\n\n\n\nAbout {palmerpenguin}\n\n\n\nThe palmerpenguins data contains size measurements for three penguin species (Chinstrap, Gentoo and Adelie) observed on three islands in the Palmer Archipelago, Antarctica (Torgersen, Biscoe, and Dream).\n\n\n\n\n15.4.2 Adding text to the UI: Title and Subtitle\nWe will do this in the UI withing fluidPage(). Remember this is a layout function that creates the basic visual structure of your app page.\nLet’s add a title and subtitle to our app. Make sure they are separated with a coma!\n\n# user interface ----\nui <- fluidPage(\n \n # app title ----\n \"My App Title\",\n \n # app subtitle ----\n \"Exploring Antarctic Penguin Data\"\n \n )\n\n\n\n15.4.3 Style text in the UI\nThe UI is actually an HTML document. We can style our text by adding static HTML elements using tags – a list of functions that parallel common HTML tags (e.g. <h1> == tags$h1()) The most common tags also have wrapper functions (e.g. h1()).\n\n# user interface ----\nui <- fluidPage(\n \n # app title ----\n tags$h1(\"My App Title\"), # alternatively, you can use the `h1()` wrapper function\n \n # app subtitle ----\n h4(strong(\"Exploring Antarctic Penguin Data\")) # alternatively, `tags$h4(tags$strong(\"text\"))`\n \n )\n\n\n\nAdding intupts and outputs\nNext, we will begin to add some inputs and outputs to our UI inside fluidPage(). Anything that you put into fluidPage() will appear in our app’s user interface. We want inputs and outputs to show up there.\n\nStep 1: add an input to your app (slider widget)\n\n# user interface ----\nui <- fluidPage(\n \n # app title ----\n tags$h1(\"My App Title\"), # alternatively, you can use the `h1()` wrapper function\n \n # app subtitle ----\n h4(strong(\"Exploring Antarctic Penguin Data\")), # alternatively, `tags$h4(tags$strong(\"text\"))`\n \n # body mass slider input ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000))\n \n )\n\n\n\nStep 2: add an output “placeholder” in the UI\nOutputs in the UI create placeholders which are later filled by the server function.\nSimilar to input functions, all output functions take the same first argument, outputId (note Id not ID), which connects the front end UI with the back end server. For example, if your UI contains an output function with an outputId = \"plot\", the server function will access it (or in other words, know to place the plot in that particular placeholder) using the syntax output$plot. \n\n# user interface ----\nui <- fluidPage(\n \n # app title ----\n tags$h1(\"My App Title\"), # alternatively, you can use the `h1()` wrapper function\n \n # app subtitle ----\n h4(strong(\"Exploring Antarctic Penguin Data\")), # alternatively, `tags$h4(tags$strong(\"text\"))`\n \n # body mass slider input ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000)),\n \n # body mass plot ouput ----\n plotOutput(outputId = \"bodyMass_scatterplot_output\")\n \n )\n\nOkay, it looks like nothing changed?? Remember, *Output() functions create placeholders, but we have not yet written the server instructions on how to fill and update those placeholders. We can inspect the HTML and see that there is, in fact, a placeholder area awaiting our eventual output, which will be a plot named “bodyMass_scatterplot_output”:\n\n\n\nSource: Intro to Shiny - Building reactive apps and dashboards, MEDS, UCSB\n\n\n\n\n\n\nTell the server how to assemble inputs into outputs: Adding reactive scatterplot\nNow that we’ve designed our input / output in the UI, we need to write the server instructions (i.e. write the server function) on how to use the input value(s) (i.e. penguin body mass range via a slider input) to update the output (scatter plot).\nThe server function is defined with two arguments, input and output, both of which are list-like objects. You must define both of these arguments within the server function. input contains the values of all the different inputs at any given time, while output is where you’ll save output objects to be displayed in the app.\nRULES\n\nSave objects you want to display to output$<id>\nBuild reactive objects using a render*() function\nAccess input values with input$\n\n\nRule 1: Save objects you want to display to output$<id>\n\n# load packages ----\nlibrary(shiny)\n\n# user interface ----\nui <- fluidPage(\n \n # ~ previous code omitted for brevity ~\n \n # body mass slider ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000)),\n \n # body mass plot output ----\n plotOutput(outputId = \"bodyMass_scatterplot_output\") \n \n)\n\n# server instructions ----\nserver <- function(input, output) {\n \n # render penguin scatter plot ----\n output$bodyMass_scatterplot_output <- # code to generate plot here\n \n}\n\nNote: In the UI, our outputId is quoted (“bodyMass_scatterplot_output”), but not in the server (bodyMass_scatterplot_output).\n\n\nRule 2: Build reactive objects with render*()\nEach *Output() function in the UI is coupled with a render*() function in the server, which contains the “instructions” for creating the output based on user inputs (or in other words, the instructions for making your output reactive).\n\n\n\n\nOutput function\nRender function\n\n\n\n\ndataTableOutput()\nrenderDataTable()\n\n\nimageOutput()\nrenderImage()\n\n\nplotOutput()\nrenderPlot()\n\n\ntableOutput()\nrenderTable()\n\n\ntextOutput()\nrenderText()\n\n\n\n\n\n# load packages ----\nlibrary(shiny)\n\n# user interface ----\nui <- fluidPage(\n \n # ~ previous code omitted for brevity ~\n \n # body mass slider ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000)),\n \n # body mass plot output ----\n plotOutput(outputId = \"bodyMass_scatterplot_output\") \n \n)\n\n# server instructions ----\nserver <- function(input, output) {\n \n # render penguin scatter plot ----\n output$bodyMass_scatterplot_output <- renderPlot({\n \n # code to generate plot here\n \n }) \n}\n\n\n\n\n\n\n\n\nAside: Write the code for the output objects in separate script first\n\n\n\nIt is generally easier to experiment with the R objects you wan to show in your app (e.g. plots) in a separate script first and then copy the code over to your app. For example, if we want to make a scatter plot showing the relationship between flipper length and bill length for the different penguin species on palmerpenguins we would start by opening a new R script and write the code for this plot.\nIn RStudio, go to File > New File > RScript. Save this file as practice-script.R into the scratch folder. Now let’s copy and paste the code below. This code creates our scatter plot.\n\n# load packages ----\nlibrary(palmerpenguins)\nlibrary(ggplot2)\n\n# create scatterplot ----\nggplot(na.omit(penguins), \n aes(x = flipper_length_mm, y = bill_length_mm, \n color = species, shape = species)) +\n geom_point() +\n scale_color_manual(values = c(\"Adelie\" = \"darkorange\", \"Chinstrap\" = \"purple\", \"Gentoo\" = \"cyan4\")) +\n scale_shape_manual(values = c(\"Adelie\" = 19, \"Chinstrap\" = 17, \"Gentoo\" = 15)) +\n labs(x = \"Flipper length (mm)\", y = \"Bill length (mm)\", \n color = \"Penguin species\", shape = \"Penguin species\") +\n theme_minimal() +\n theme(legend.position = c(0.85, 0.2),\n legend.background = element_rect(color = \"white\"))\n\n\n\n\n\n\n\n\n\n\nNext, copy your plot code into the server\nCopy your code over to your app, placing it inside the {} (and make sure to add any additional required packages to the top of your app.R script). Run your app. What do you notice?\n\n# load packages ----\nlibrary(shiny)\nlibrary(palmerpenguins)\nlibrary(tidyverse)\n\n# user interface ----\nui <- fluidPage(\n \n # ~ previous code omitted for brevity ~\n \n # body mass slider ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000)),\n \n # body mass plot output ----\n plotOutput(outputId = \"bodyMass_scatterplot_output\")\n \n)\n\n# server instructions ----\nserver <- function(input, output) {\n \n # render penguin scatter plot ----\n output$bodyMass_scatterplot_output <- renderPlot({ \n ggplot(na.omit(penguins),\n aes(x = flipper_length_mm, y = bill_length_mm,\n color = species, shape = species)) + \n geom_point() + \n scale_color_manual(values = c(\"Adelie\" = \"#FEA346\", \"Chinstrap\" = \"#B251F1\", \"Gentoo\" = \"#4BA4A4\")) +\n scale_shape_manual(values = c(\"Adelie\" = 19, \"Chinstrap\" = 17, \"Gentoo\" = 15)) +\n labs(x = \"Flipper length (mm)\", y = \"Bill length (mm)\", \n color = \"Penguin species\", shape = \"Penguin species\") + \n theme_minimal() + \n theme(legend.position = c(0.85, 0.2), \n legend.background = element_rect(color = \"white\")) \n })\n}\n\n\n\n\n\nGreat! We have plot! But… It is not reactive. We have not yet told the server how to update the plot based on user inputs via the sliderInput() in the UI. Let’s do that next.\n\n\n\n\n\n\n\nAside: Practice filtering data in a separate script\n\n\n\nGo back to out practice script practice-script.R and create a new data frame where we filter the body_mass_g column for observations within a specific range of values (in this example, values ranging from 3000 - 4000).\n\n# filter penguins df for observations where body_mass_g >= 3000 & <= 4000 ----\nbody_mass_df <- penguins %>% \n filter(body_mass_g %in% c(3000:4000))\n\nThen, plot the new filtered data frame.\n\n# plot new, filtered data ----\nggplot(na.omit(body_mass_df), # plot 'body_mass_df' rather than 'penguins' df\n aes(x = flipper_length_mm, y = bill_length_mm, \n color = species, shape = species)) +\n geom_point() +\n scale_color_manual(values = c(\"Adelie\" = \"#FEA346\", \"Chinstrap\" = \"#B251F1\", \"Gentoo\" = \"#4BA4A4\")) +\n scale_shape_manual(values = c(\"Adelie\" = 19, \"Chinstrap\" = 17, \"Gentoo\" = 15)) +\n labs(x = \"Flipper length (mm)\", y = \"Bill length (mm)\", \n color = \"Penguin species\", shape = \"Penguin species\") +\n theme_minimal() +\n theme(legend.position = c(0.85, 0.2),\n legend.background = element_rect(color = \"white\"))\n\n\n\n\nWhich part of our code needs to be updated when a user changes the slider range input?\nFor example if someone inputs the following range:\n\n\n\n\n\nThe code has to do something like this.\n\nbody_mass_df <- penguins %>% \n filter(body_mass_g %in% c(2857:5903))\n\n\n\n\nRule 3: Access input values with input$<id>\nRemember that in our UI we we gave the slidrInput() an inputID = body_mass_input.\n\n# body mass slider ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\", \n min = 2700, max = 6300, value = c(3000, 4000))\n\nNow we need to add the input piece on the server side. We can access the values of that slider input in the server using the syntax, input$body_mass_input. If you want your output to change according to the input values, substitute hard-coded values (e.g. 2857:5903) with the input values from the UI. For example, c(input$body_mass_input[1]:input$body_mass_input[2]\n\n\n\n\n\n\n\nReactive Data Frame\n\n\n\nWe need to create a reactive data frame that is able to update according to the input. For this we use the reactive() function.\nWhen you call your reactive data frame in your ggplot, the data frame name must be followed by ()\n\n\n\n\n# load packages ----\nlibrary(shiny)\nlibrary(palmerpenguins)\nlibrary(tidyverse)\n\n# user interface ----\nui <- fluidPage(\n \n # ~ previous code omitted for brevity ~\n \n # body mass slider ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000)),\n \n # body mass plot output ----\n plotOutput(outputId = \"bodyMass_scatterplot_output\")\n \n)\n\n# server instructions ----\nserver <- function(input, output) {\n \n # filter body masses ----\n body_mass_df <- reactive({ \n penguins %>% \n filter(body_mass_g %in% c(input$body_mass_input[1]:input$body_mass_input[2])) \n })\n \n # render penguin scatter plot ----\n output$bodyMass_scatterplot_output <- renderPlot({ \n ggplot(na.omit(body_mass_df()),\n aes(x = flipper_length_mm, y = bill_length_mm,\n color = species, shape = species)) + \n geom_point() + \n scale_color_manual(values = c(\"Adelie\" = \"#FEA346\", \"Chinstrap\" = \"#B251F1\", \"Gentoo\" = \"#4BA4A4\")) +\n scale_shape_manual(values = c(\"Adelie\" = 19, \"Chinstrap\" = 17, \"Gentoo\" = 15)) +\n labs(x = \"Flipper length (mm)\", y = \"Bill length (mm)\", \n color = \"Penguin species\", shape = \"Penguin species\") + \n theme_minimal() + \n theme(legend.position = c(0.85, 0.2), \n legend.background = element_rect(color = \"white\")) \n })\n}\n\nNow let’s tun the app! We should now see a reactive Shiny app. Note that reactivity automatically occurs whenever you use an input value to render an output object.\n\n\n\n15.4.4 Recap: Steps to create a reactive Shiny app\n\nWe created an app.R file in it’s own directory and began our app with the template, though you can also create a two-file Shiny app by using separate ui.R and server.R files.\nWe added an input to the fluidPage() in our UI using an *Input() function and gave it a unique inputId (e.g. inputId = \"unique_input_Id_name\")\nWe created a placeholder for our reactive object by using an *Output() function in the fluidPage() of our UI and gave it an outputId (e.g. outputId = \"output_Id_name\")\nWe wrote the server instructions for how to assemble inputs into outputs, following these rules:\n\n\nSave objects that you want to display to output$<id>\nBuild reactive objects using a render*() function (and similarly, build reactive data frames using reactive() )\nAccess input values with input$<id>\n\nAnd… we saw that reactivity automatically occurs whenever we use an input value to render an output object.", "crumbs": [ "15  Introduction to Shiny" ] }, { - "objectID": "session_15.html#your-turn", - "href": "session_15.html#your-turn", + "objectID": "session_15.html#your-turn-build-on-our-1-file-app", + "href": "session_15.html#your-turn-build-on-our-1-file-app", "title": "15  Introduction to Shiny", - "section": "15.5 Your turn", - "text": "15.5 Your turn\n\n\n\n\n\n\nAdd another reactive widget\n\n\n\nWorking alone or in groups, add a reactive DT datatable to your app with a checkboxGroupInput (widget) that allows users to select which year(s) to include in the table. Configure your checkboxGroupInput so that the years 2007 and 2008 are pre-selected.\n\n\nRemember that the DT package allows you to create interactive tables where you can filter, sort, and do lots of other neat things tables in HTML format.\nOnce you’ve added the new feature your app should look like this:\n\n\n\nSource: Intro to Shiny - Building reactive apps and dashboards, MEDS, UCSB\n\n\n\n\n\n\n\n\n\nTips\n\n\n\n\nUse ?checkboxGroupInput to learn more about which arguments you need (remember, all inputs require an inputId and oftentimes a label, but there are others required to make this work as well)\nBoth {shiny} and {DT} packages have functions named dataTableOutput() and renderDataTable() – The DT functions allows you to create both server-side and ui-side DataTables and supports additional DataTables features while Shiny functions only provides server-side DataTables. Be sure to use the ones from the {DT} package using the syntax packageName::functionName().\nThere are lots of ways to customize DT tables, but to create a basic one, all you need is DT::dataTable(your_dataframe)\n\nRemember to follow the steps outlined above:\n\nAdd an input (e.g. checkboxGroupInput) to the UI that users can interact with.\nAdd an output (e.g. DT::datatableOutput) to the UI that creates a placeholder space to fill with our eventual reactive output.\nTell the server how to assemble inputs into outputs following 3 rules:\n\n\nSave objects you want to display to output$<id>\nBuild reactive objects using a render*() function\nAccess input values with input$<id>\n\n\n\n\n\n\nExercise 1: A Solution\n# load libraries ----\nlibrary(shiny)\nlibrary(tidyverse)\nlibrary(DT)\n\n# user interface ----\nui <- fluidPage(\n \n # app title ----\n tags$h1(\"My App Title\"), # alternatively, you can use the `h1()` wrapper function\n \n # app subtitle ----\n h4(strong(\"Exploring Antarctic Penguin Data\")), # alternatively, `tags$h4(tags$strong(\"text\"))`\n \n # body mass slider input ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000)),\n \n # body mass plot output ----\n plotOutput(outputId = \"bodyMass_scatterplot_output\"),\n \n # year checkbox input ----\n checkboxGroupInput(inputId = \"year_select\", \n label = \"Select year(s)\" ,\n choices = c(2007, 2008, 2009),\n selected = c(2007, 2008)),\n \n # interactive table output ----\n DT::dataTableOutput(outputId = \"interactive_table_output\")\n \n)\n\n\n# server instructions ----\nserver <- function(input, output) {\n \n # filter body masses ----\n body_mass_df <- reactive({ \n penguins %>% \n filter(body_mass_g %in% c(input$body_mass_input[1]:input$body_mass_input[2])) \n })\n \n # reactive scatterplot ---\n output$bodyMass_scatterplot_output <- renderPlot({\n ggplot(na.omit(body_mass_df()),\n aes(x = flipper_length_mm, y = bill_length_mm,\n color = species, shape = species)) + \n geom_point() + \n scale_color_manual(values = c(\"Adelie\" = \"#FEA346\", \"Chinstrap\" = \"#B251F1\", \"Gentoo\" = \"#4BA4A4\")) +\n scale_shape_manual(values = c(\"Adelie\" = 19, \"Chinstrap\" = 17, \"Gentoo\" = 15)) +\n labs(x = \"Flipper length (mm)\", y = \"Bill length (mm)\", \n color = \"Penguin species\", shape = \"Penguin species\") + \n theme_minimal() + \n theme(legend.position = c(0.85, 0.2), \n legend.background = element_rect(color = \"white\"))\n })\n \n \n # reactive-table ----\n penguins_years <- reactive({\n penguins %>% \n filter(year %in% c(input$year_select))\n })\n \n output$interactive_table_output <- DT::renderDataTable(\n \n DT::datatable(penguins_years(),\n options = list(pagelength = 10),\n rownames = FALSE)\n )\n \n}\n\n# combine UI & server into an app ----\nshinyApp(ui = ui, server = server)\n\n\n\n\n\n\n\n\n\nCommon Mistakes\n\n\n\nWe all make mistakes! Specially when building a Shiny app. Here a few common mistakes to be on the lookout:\n\nMisspelling inputId as inputID (or outputId as outputID)\nMisspelling your inputId (or outputId) name in the server (e.g. UI: inputId = \"myInputID\", server: input$my_Input_ID)\nRepeating inputIds (each must be unique)\nForgetting to separate UI elements with a comma, ,. Commas are a thing in Shiny.\nForgetting the set of parentheses when calling the name of a reactive data frame (e.g. ggplot(my_reactive_df, aes(...)) should be ggplot(my_reactive_df(), aes(...)) )", + "section": "15.5 Your turn: Build on our 1-file app", + "text": "15.5 Your turn: Build on our 1-file app\n\n\n\n\n\n\nAdd another reactive widget\n\n\n\nWorking alone or in groups, add a reactive DT datatable to your app with a checkboxGroupInput (widget) that allows users to select which year(s) to include in the table. Configure your checkboxGroupInput so that the years 2007 and 2008 are pre-selected.\n\n\nRemember that the DT package allows you to create interactive tables where you can filter, sort, and do lots of other neat things tables in HTML format.\nOnce you’ve added the new feature your app should look like this:\n\n\n\nSource: Intro to Shiny - Building reactive apps and dashboards, MEDS, UCSB\n\n\n\n\n\n\n\n\n\nTips\n\n\n\n\nUse ?checkboxGroupInput to learn more about which arguments you need (remember, all inputs require an inputId and oftentimes a label, but there are others required to make this work as well)\nBoth {shiny} and {DT} packages have functions named dataTableOutput() and renderDataTable() – The DT functions allows you to create both server-side and ui-side DataTables and supports additional DataTables features while Shiny functions only provides server-side DataTables. Be sure to use the ones from the {DT} package using the syntax packageName::functionName().\nThere are lots of ways to customize DT tables, but to create a basic one, all you need is DT::dataTable(your_dataframe)\n\nRemember to follow the steps outlined above:\n\nAdd an input (e.g. checkboxGroupInput) to the UI that users can interact with.\nAdd an output (e.g. DT::datatableOutput) to the UI that creates a placeholder space to fill with our eventual reactive output.\nTell the server how to assemble inputs into outputs following 3 rules:\n\n\nSave objects you want to display to output$<id>\nBuild reactive objects using a render*() function\nAccess input values with input$<id>\n\n\n\n\n\n\nExercise 1: A Solution\n# load libraries ----\nlibrary(shiny)\nlibrary(tidyverse)\nlibrary(DT)\n\n# user interface ----\nui <- fluidPage(\n \n # app title ----\n tags$h1(\"My App Title\"), # alternatively, you can use the `h1()` wrapper function\n \n # app subtitle ----\n h4(strong(\"Exploring Antarctic Penguin Data\")), # alternatively, `tags$h4(tags$strong(\"text\"))`\n \n # body mass slider input ----\n sliderInput(inputId = \"body_mass_input\", label = \"Select a range of body masses (g):\",\n min = 2700, max = 6300, value = c(3000, 4000)),\n \n # body mass plot output ----\n plotOutput(outputId = \"bodyMass_scatterplot_output\"),\n \n # year checkbox input ----\n checkboxGroupInput(inputId = \"year_select\", \n label = \"Select year(s)\" ,\n choices = c(2007, 2008, 2009),\n selected = c(2007, 2008)),\n \n # interactive table output ----\n DT::dataTableOutput(outputId = \"interactive_table_output\")\n \n)\n\n\n# server instructions ----\nserver <- function(input, output) {\n \n # filter body masses ----\n body_mass_df <- reactive({ \n penguins %>% \n filter(body_mass_g %in% c(input$body_mass_input[1]:input$body_mass_input[2])) \n })\n \n # reactive scatterplot ---\n output$bodyMass_scatterplot_output <- renderPlot({\n ggplot(na.omit(body_mass_df()),\n aes(x = flipper_length_mm, y = bill_length_mm,\n color = species, shape = species)) + \n geom_point() + \n scale_color_manual(values = c(\"Adelie\" = \"#FEA346\", \"Chinstrap\" = \"#B251F1\", \"Gentoo\" = \"#4BA4A4\")) +\n scale_shape_manual(values = c(\"Adelie\" = 19, \"Chinstrap\" = 17, \"Gentoo\" = 15)) +\n labs(x = \"Flipper length (mm)\", y = \"Bill length (mm)\", \n color = \"Penguin species\", shape = \"Penguin species\") + \n theme_minimal() + \n theme(legend.position = c(0.85, 0.2), \n legend.background = element_rect(color = \"white\"))\n })\n \n \n # reactive-table ----\n penguins_years <- reactive({\n penguins %>% \n filter(year %in% c(input$year_select))\n })\n \n output$interactive_table_output <- DT::renderDataTable(\n \n DT::datatable(penguins_years(),\n options = list(pagelength = 10),\n rownames = FALSE)\n )\n \n}\n\n# combine UI & server into an app ----\nshinyApp(ui = ui, server = server)\n\n\n\n\n\n\n\n\n\nCommon Mistakes\n\n\n\nWe all make mistakes! Specially when building a Shiny app. Here a few common mistakes to be on the lookout:\n\nMisspelling inputId as inputID (or outputId as outputID)\nMisspelling your inputId (or outputId) name in the server (e.g. UI: inputId = \"myInputID\", server: input$my_Input_ID)\nRepeating inputIds (each must be unique)\nForgetting to separate UI elements with a comma, ,. Commas are a thing in Shiny.\nForgetting the set of parentheses when calling the name of a reactive data frame (e.g. ggplot(my_reactive_df, aes(...)) should be ggplot(my_reactive_df(), aes(...)) )", "crumbs": [ "15  Introduction to Shiny" ] diff --git a/public/2024-06-delta/session_12.html b/public/2024-06-delta/session_12.html index 47ef7b65..76b261b6 100644 --- a/public/2024-06-delta/session_12.html +++ b/public/2024-06-delta/session_12.html @@ -1026,8 +1026,8 @@

datatable(locations)
-
- +
+
@@ -1044,8 +1044,8 @@

popup = ~ restore_loc )
-
- +
+


@@ -1070,8 +1070,8 @@

color = "white", opacity = 1)
-
- +
+


@@ -1100,8 +1100,8 @@

color = "white", opacity = 1)
-
- +
+


diff --git a/public/2024-06-delta/session_13.html b/public/2024-06-delta/session_13.html index 563525d0..6ff27360 100644 --- a/public/2024-06-delta/session_13.html +++ b/public/2024-06-delta/session_13.html @@ -1092,8 +1092,8 @@

m
-
- +
+

We can add labels, legends, and a color scale.

@@ -1118,8 +1118,8 @@

m
-
- +
+

We can also add the individual communities, with popup labels showing their population, on top of that!

@@ -1155,8 +1155,8 @@

m
-
- +
+
diff --git a/public/2024-06-delta/session_13_files/figure-html/unnamed-chunk-28-1.png b/public/2024-06-delta/session_13_files/figure-html/unnamed-chunk-28-1.png index 22ca52e6..a054a435 100644 Binary files a/public/2024-06-delta/session_13_files/figure-html/unnamed-chunk-28-1.png and b/public/2024-06-delta/session_13_files/figure-html/unnamed-chunk-28-1.png differ diff --git a/public/2024-06-delta/session_15.html b/public/2024-06-delta/session_15.html index 4f172789..667127f6 100644 --- a/public/2024-06-delta/session_15.html +++ b/public/2024-06-delta/session_15.html @@ -309,7 +309,7 @@

Table of contents

  • Tell the server how to assemble inputs into outputs: Adding reactive scatterplot
  • 15.4.4 Recap: Steps to create a reactive Shiny app
  • -
  • 15.5 Your turn
  • +
  • 15.5 Your turn: Build on our 1-file app
  • 15.6 Layouts
  • 15.7 Resources
  • @@ -468,7 +468,7 @@

    @@ -583,7 +583,7 @@

      -
    1. In your project repo, create a sub-directory to house your app. Name it single-file-app.

    2. +
    3. In your project repo, create a sub-directory to house your app. Name it single-file-app. And a dub-directory for all our scratch code (e.g practice plots or subset df.)

    4. Create a new R script inside single-file-app/ and name it app.R – you must name your script app.R.

    5. Copy or type the following code into app.R, or use the shinyapp snippet to automatically generate a shiny app template.

    @@ -1055,8 +1055,8 @@

    -

    15.5 Your turn

    +
    +

    15.5 Your turn: Build on our 1-file app